crypt32: Fix encoding cert issuer/subject unique ids.
[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     todo_wine
3123     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3124     if (ret)
3125     {
3126         CERT_INFO *info = (CERT_INFO *)buf;
3127
3128         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3129         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3130          info->dwVersion);
3131         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3132          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3133         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3134          "unexpected issuer unique id value\n");
3135         LocalFree(buf);
3136     }
3137     /* Now check with serial number, subject and issuer specified */
3138     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3139      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3140     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3141     if (buf)
3142     {
3143         CERT_INFO *info = (CERT_INFO *)buf;
3144
3145         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3146         ok(info->SerialNumber.cbData == 1,
3147          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3148         ok(*info->SerialNumber.pbData == *serialNum,
3149          "Expected serial number %d, got %d\n", *serialNum,
3150          *info->SerialNumber.pbData);
3151         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3152          "Wrong size %d\n", info->Issuer.cbData);
3153         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3154          "Unexpected issuer\n");
3155         ok(info->Subject.cbData == sizeof(encodedCommonName),
3156          "Wrong size %d\n", info->Subject.cbData);
3157         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3158          info->Subject.cbData), "Unexpected subject\n");
3159         LocalFree(buf);
3160     }
3161     /* Check again with pub key specified */
3162     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3163      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3164      &buf, &size);
3165     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3166     if (buf)
3167     {
3168         CERT_INFO *info = (CERT_INFO *)buf;
3169
3170         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3171         ok(info->SerialNumber.cbData == 1,
3172          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3173         ok(*info->SerialNumber.pbData == *serialNum,
3174          "Expected serial number %d, got %d\n", *serialNum,
3175          *info->SerialNumber.pbData);
3176         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3177          "Wrong size %d\n", info->Issuer.cbData);
3178         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3179          "Unexpected issuer\n");
3180         ok(info->Subject.cbData == sizeof(encodedCommonName),
3181          "Wrong size %d\n", info->Subject.cbData);
3182         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3183          info->Subject.cbData), "Unexpected subject\n");
3184         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3185          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3186          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3187         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3188          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3189         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3190          sizeof(aKey)), "Unexpected public key\n");
3191         LocalFree(buf);
3192     }
3193 }
3194
3195 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3196  0xe, 0xf };
3197
3198 static const BYTE signedBigCert[] = {
3199  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3200  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3201  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3202  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3203  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3204  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3205  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3206  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3207  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3208  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3209  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3210  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3211
3212 static void test_encodeCert(DWORD dwEncoding)
3213 {
3214     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3215      * also that bigCert is a NULL-terminated string, so don't count its
3216      * last byte (otherwise the signed cert won't decode.)
3217      */
3218     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3219      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3220     BOOL ret;
3221     BYTE *buf = NULL;
3222     DWORD bufSize = 0;
3223
3224     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3225      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3226     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3227     if (buf)
3228     {
3229         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3230         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3231         LocalFree(buf);
3232     }
3233 }
3234
3235 static void test_decodeCert(DWORD dwEncoding)
3236 {
3237     BOOL ret;
3238     BYTE *buf = NULL;
3239     DWORD size = 0;
3240
3241     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3242      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3243     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3244     if (buf)
3245     {
3246         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3247
3248         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3249          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3250         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3251          "Unexpected cert\n");
3252         ok(info->Signature.cbData == sizeof(hash),
3253          "Wrong signature size %d\n", info->Signature.cbData);
3254         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3255          "Unexpected signature\n");
3256         LocalFree(buf);
3257     }
3258     /* A signed cert decodes as a CERT_INFO too */
3259     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3260      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3261     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3262     if (buf)
3263     {
3264         CERT_INFO *info = (CERT_INFO *)buf;
3265
3266         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3267         ok(info->SerialNumber.cbData == 1,
3268          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3269         ok(*info->SerialNumber.pbData == *serialNum,
3270          "Expected serial number %d, got %d\n", *serialNum,
3271          *info->SerialNumber.pbData);
3272         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3273          "Wrong size %d\n", info->Issuer.cbData);
3274         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3275          "Unexpected issuer\n");
3276         ok(info->Subject.cbData == sizeof(encodedCommonName),
3277          "Wrong size %d\n", info->Subject.cbData);
3278         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3279          info->Subject.cbData), "Unexpected subject\n");
3280         LocalFree(buf);
3281     }
3282 }
3283
3284 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3285 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3286  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3287  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3288 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3289  0x00, 0x03 };
3290 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3291  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3292  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3293 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3294  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3295  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3296  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3297  0x2e, 0x6f, 0x72, 0x67 };
3298 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3299  CRL_REASON_AFFILIATION_CHANGED;
3300
3301 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3302 {
3303     CRL_DIST_POINTS_INFO info = { 0 };
3304     CRL_DIST_POINT point = { { 0 } };
3305     CERT_ALT_NAME_ENTRY entry = { 0 };
3306     BOOL ret;
3307     BYTE *buf = NULL;
3308     DWORD size = 0;
3309
3310     /* Test with an empty info */
3311     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3312      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3313     ok(!ret && GetLastError() == E_INVALIDARG,
3314      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3315     /* Test with one empty dist point */
3316     info.cDistPoint = 1;
3317     info.rgDistPoint = &point;
3318     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3319      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3320     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3321     if (buf)
3322     {
3323         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3324         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3325         LocalFree(buf);
3326     }
3327     /* A dist point with an invalid name */
3328     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3329     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3330     U(entry).pwszURL = (LPWSTR)nihongoURL;
3331     U(point.DistPointName).FullName.cAltEntry = 1;
3332     U(point.DistPointName).FullName.rgAltEntry = &entry;
3333     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3334      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3335     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3336      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3337     /* The first invalid character is at index 7 */
3338     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3339      "Expected invalid char at index 7, got %d\n",
3340      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3341     /* A dist point with (just) a valid name */
3342     U(entry).pwszURL = (LPWSTR)url;
3343     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3344      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3345     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3346     if (buf)
3347     {
3348         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3349         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3350         LocalFree(buf);
3351     }
3352     /* A dist point with (just) reason flags */
3353     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3354     point.ReasonFlags.cbData = sizeof(crlReason);
3355     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3356     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3357      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3358     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3359     if (buf)
3360     {
3361         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3362         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3363         LocalFree(buf);
3364     }
3365     /* A dist point with just an issuer */
3366     point.ReasonFlags.cbData = 0;
3367     point.CRLIssuer.cAltEntry = 1;
3368     point.CRLIssuer.rgAltEntry = &entry;
3369     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3370      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3371     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3372     if (buf)
3373     {
3374         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3375         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3376         LocalFree(buf);
3377     }
3378     /* A dist point with both a name and an issuer */
3379     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3380     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3381      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3382     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3383     if (buf)
3384     {
3385         ok(size == sizeof(distPointWithUrlAndIssuer),
3386          "Wrong size %d\n", size);
3387         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3388         LocalFree(buf);
3389     }
3390 }
3391
3392 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3393 {
3394     BOOL ret;
3395     BYTE *buf = NULL;
3396     DWORD size = 0;
3397     PCRL_DIST_POINTS_INFO info;
3398     PCRL_DIST_POINT point;
3399     PCERT_ALT_NAME_ENTRY entry;
3400
3401     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3402      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3403      &buf, &size);
3404     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3405     if (ret)
3406     {
3407         info = (PCRL_DIST_POINTS_INFO)buf;
3408         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3409          "Wrong size %d\n", size);
3410         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3411          info->cDistPoint);
3412         point = info->rgDistPoint;
3413         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3414          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3415          point->DistPointName.dwDistPointNameChoice);
3416         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3417         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3418         LocalFree(buf);
3419     }
3420     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3421      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3422      &buf, &size);
3423     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3424     if (ret)
3425     {
3426         info = (PCRL_DIST_POINTS_INFO)buf;
3427         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3428          "Wrong size %d\n", size);
3429         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3430          info->cDistPoint);
3431         point = info->rgDistPoint;
3432         ok(point->DistPointName.dwDistPointNameChoice ==
3433          CRL_DIST_POINT_FULL_NAME,
3434          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3435          point->DistPointName.dwDistPointNameChoice);
3436         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3437          "Expected 1 name entry, got %d\n",
3438          U(point->DistPointName).FullName.cAltEntry);
3439         entry = U(point->DistPointName).FullName.rgAltEntry;
3440         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3441          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3442         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3443         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3444         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3445         LocalFree(buf);
3446     }
3447     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3448      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3449      NULL, &buf, &size);
3450     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3451     if (ret)
3452     {
3453         info = (PCRL_DIST_POINTS_INFO)buf;
3454         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3455          "Wrong size %d\n", size);
3456         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3457          info->cDistPoint);
3458         point = info->rgDistPoint;
3459         ok(point->DistPointName.dwDistPointNameChoice ==
3460          CRL_DIST_POINT_NO_NAME,
3461          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3462          point->DistPointName.dwDistPointNameChoice);
3463         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3464          "Expected reason length\n");
3465         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3466          "Unexpected reason\n");
3467         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3468         LocalFree(buf);
3469     }
3470     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3471      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3472      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3473     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3474     if (ret)
3475     {
3476         info = (PCRL_DIST_POINTS_INFO)buf;
3477         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3478          "Wrong size %d\n", size);
3479         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3480          info->cDistPoint);
3481         point = info->rgDistPoint;
3482         ok(point->DistPointName.dwDistPointNameChoice ==
3483          CRL_DIST_POINT_FULL_NAME,
3484          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3485          point->DistPointName.dwDistPointNameChoice);
3486         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3487          "Expected 1 name entry, got %d\n",
3488          U(point->DistPointName).FullName.cAltEntry);
3489         entry = U(point->DistPointName).FullName.rgAltEntry;
3490         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3491          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3492         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3493         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3494         ok(point->CRLIssuer.cAltEntry == 1,
3495          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3496         entry = point->CRLIssuer.rgAltEntry;
3497         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3498          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3499         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3500         LocalFree(buf);
3501     }
3502 }
3503
3504 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3505 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3506 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3507  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3508  0x67 };
3509
3510 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3511 {
3512     BOOL ret;
3513     BYTE *buf = NULL;
3514     DWORD size = 0;
3515     CRL_ISSUING_DIST_POINT point = { { 0 } };
3516     CERT_ALT_NAME_ENTRY entry;
3517
3518     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3519      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3520     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3521     {
3522         skip("no X509_ISSUING_DIST_POINT encode support\n");
3523         return;
3524     }
3525     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3526      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3527     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3528      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3529     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3530     if (buf)
3531     {
3532         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3533         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3534         LocalFree(buf);
3535     }
3536     /* nonsensical flags */
3537     point.fOnlyContainsUserCerts = TRUE;
3538     point.fOnlyContainsCACerts = TRUE;
3539     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3540      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3541     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3542     if (buf)
3543     {
3544         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3545         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3546         LocalFree(buf);
3547     }
3548     /* unimplemented name type */
3549     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3550     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3551     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3552      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3553     ok(!ret && GetLastError() == E_INVALIDARG,
3554      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3555     /* empty name */
3556     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3557     U(point.DistPointName).FullName.cAltEntry = 0;
3558     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3559      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3560     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3561     if (buf)
3562     {
3563         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3564         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3565         LocalFree(buf);
3566     }
3567     /* name with URL entry */
3568     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3569     U(entry).pwszURL = (LPWSTR)url;
3570     U(point.DistPointName).FullName.cAltEntry = 1;
3571     U(point.DistPointName).FullName.rgAltEntry = &entry;
3572     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3573      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3574     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3575     if (buf)
3576     {
3577         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3578         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3579         LocalFree(buf);
3580     }
3581 }
3582
3583 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3584  const CERT_ALT_NAME_ENTRY *got)
3585 {
3586     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3587      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3588      got->dwAltNameChoice);
3589     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3590     {
3591         switch (got->dwAltNameChoice)
3592         {
3593         case CERT_ALT_NAME_RFC822_NAME:
3594         case CERT_ALT_NAME_DNS_NAME:
3595         case CERT_ALT_NAME_EDI_PARTY_NAME:
3596         case CERT_ALT_NAME_URL:
3597         case CERT_ALT_NAME_REGISTERED_ID:
3598             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3599              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3600              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3601              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3602              "Unexpected name\n");
3603             break;
3604         case CERT_ALT_NAME_X400_ADDRESS:
3605         case CERT_ALT_NAME_DIRECTORY_NAME:
3606         case CERT_ALT_NAME_IP_ADDRESS:
3607             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3608                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3609             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3610                        U(*got).IPAddress.cbData), "Unexpected value\n");
3611             break;
3612         }
3613     }
3614 }
3615
3616 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3617  const CERT_ALT_NAME_INFO *got)
3618 {
3619     DWORD i;
3620
3621     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3622      expected->cAltEntry, got->cAltEntry);
3623     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3624         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3625 }
3626
3627 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3628  const CRL_DIST_POINT_NAME *got)
3629 {
3630     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3631      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3632     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3633         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3634 }
3635
3636 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3637  const CRL_ISSUING_DIST_POINT *got)
3638 {
3639     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3640     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3641      "Unexpected fOnlyContainsUserCerts\n");
3642     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3643      "Unexpected fOnlyContainsCACerts\n");
3644     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3645      "Unexpected reason flags\n");
3646     ok(got->fIndirectCRL == expected->fIndirectCRL,
3647      "Unexpected fIndirectCRL\n");
3648 }
3649
3650 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3651 {
3652     BOOL ret;
3653     BYTE *buf = NULL;
3654     DWORD size = 0;
3655     CRL_ISSUING_DIST_POINT point = { { 0 } };
3656
3657     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3658      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3659      &buf, &size);
3660     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3661     {
3662         skip("no X509_ISSUING_DIST_POINT decode support\n");
3663         return;
3664     }
3665     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3666     if (ret)
3667     {
3668         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3669         LocalFree(buf);
3670     }
3671     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3672      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3673      &buf, &size);
3674     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3675     if (ret)
3676     {
3677         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3678         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3679         LocalFree(buf);
3680     }
3681     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3682      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3683      &buf, &size);
3684     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3685     if (ret)
3686     {
3687         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3688         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3689         U(point.DistPointName).FullName.cAltEntry = 0;
3690         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3691         LocalFree(buf);
3692     }
3693     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3694      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3695     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3696     if (ret)
3697     {
3698         CERT_ALT_NAME_ENTRY entry;
3699
3700         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3701         U(entry).pwszURL = (LPWSTR)url;
3702         U(point.DistPointName).FullName.cAltEntry = 1;
3703         U(point.DistPointName).FullName.rgAltEntry = &entry;
3704         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3705         LocalFree(buf);
3706     }
3707 }
3708
3709 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3710  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3711  0x30, 0x5a };
3712 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3713  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3714  0x30, 0x30, 0x30, 0x30, 0x5a };
3715 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3716  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3717  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3718  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3719  0x5a };
3720 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3721  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3722  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3723  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3724  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3725  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3726 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3727  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3728  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3729  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3730  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3731  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3732 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3733  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3734  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3735  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3736  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3737  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3738  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3739 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3740  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3741  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3742  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3743  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3744  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3745  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3746 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3747  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3748  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3749  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3750  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3751  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3752  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3753 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3754  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3755  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3756  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3757  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3758  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3759  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3760
3761 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3762 {
3763     BOOL ret;
3764     BYTE *buf = NULL;
3765     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3766     DWORD size = 0;
3767     CRL_INFO info = { 0 };
3768     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3769     CERT_EXTENSION ext;
3770
3771     /* Test with a V1 CRL */
3772     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3773      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3774     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3775      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3776     if (buf)
3777     {
3778         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3779         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3780         LocalFree(buf);
3781     }
3782     /* Test v2 CRL */
3783     info.dwVersion = CRL_V2;
3784     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3785      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3786     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3787      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3788     if (buf)
3789     {
3790         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3791          v2CRL[1] + 2, size);
3792         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3793         LocalFree(buf);
3794     }
3795     /* v1 CRL with a name */
3796     info.dwVersion = CRL_V1;
3797     info.Issuer.cbData = sizeof(encodedCommonName);
3798     info.Issuer.pbData = (BYTE *)encodedCommonName;
3799     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3800      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3801     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3802     if (buf)
3803     {
3804         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3805         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3806         LocalFree(buf);
3807     }
3808     if (0)
3809     {
3810         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3811         info.cCRLEntry = 1;
3812         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3813          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3814         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3815          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3816     }
3817     /* now set an empty entry */
3818     info.cCRLEntry = 1;
3819     info.rgCRLEntry = &entry;
3820     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3821      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3822     if (buf)
3823     {
3824         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3825          "Wrong size %d\n", size);
3826         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3827          "Got unexpected value\n");
3828         LocalFree(buf);
3829     }
3830     /* an entry with a serial number */
3831     entry.SerialNumber.cbData = sizeof(serialNum);
3832     entry.SerialNumber.pbData = (BYTE *)serialNum;
3833     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3834      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3835     if (buf)
3836     {
3837         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3838          "Wrong size %d\n", size);
3839         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3840          "Got unexpected value\n");
3841         LocalFree(buf);
3842     }
3843     /* an entry with an extension */
3844     entry.cExtension = 1;
3845     entry.rgExtension = &criticalExt;
3846     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3847      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3848     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3849     if (buf)
3850     {
3851         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3852         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3853         LocalFree(buf);
3854     }
3855     /* a CRL with an extension */
3856     entry.cExtension = 0;
3857     info.cExtension = 1;
3858     info.rgExtension = &criticalExt;
3859     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3860      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3861     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3862     if (buf)
3863     {
3864         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3865         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3866         LocalFree(buf);
3867     }
3868     /* a v2 CRL with an extension, this time non-critical */
3869     info.dwVersion = CRL_V2;
3870     info.rgExtension = &nonCriticalExt;
3871     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3872      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3873     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3874     if (buf)
3875     {
3876         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3877         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3878         LocalFree(buf);
3879     }
3880     /* a v2 CRL with an issuing dist point extension */
3881     ext.pszObjId = oid_issuing_dist_point;
3882     ext.fCritical = TRUE;
3883     ext.Value.cbData = sizeof(urlIDP);
3884     ext.Value.pbData = (LPBYTE)urlIDP;
3885     entry.rgExtension = &ext;
3886     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3887      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3888     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3889     if (buf)
3890     {
3891         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3892         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3893         LocalFree(buf);
3894     }
3895 }
3896
3897 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3898  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3899  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3900  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3901  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3902  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3903  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3904  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3905  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3906  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3907  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3908  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3909  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3910  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3911  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3912  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3913  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3914  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3915  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3916  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3917  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3918  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3919  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3920  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3921  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3922  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3923  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3924  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3925  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3926  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3927  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3928  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3929  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3930  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3931  0xcd };
3932 static const BYTE verisignCRLWithLotsOfEntries[] = {
3933 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3934 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3935 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3936 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3937 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3938 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3939 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3940 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3941 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3942 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3943 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3944 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3945 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3946 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3947 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3948 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3949 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3950 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3951 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3952 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3953 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3954 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3955 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3956 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3957 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3958 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3959 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3960 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3961 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3962 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3963 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3964 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3965 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3966 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3967 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3968 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3969 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3970 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3971 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3972 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3973 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3974 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3975 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3976 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3977 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3978 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3979 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3980 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3981 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3982 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3983 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3984 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3985 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3986 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3987 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3988 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3989 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3990 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3991 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3992 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3993 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3994 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3995 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3996 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3997 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3998 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3999 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4000 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4001 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4002 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4003 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4004 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4005 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4006 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4007 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4008 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4009 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4010 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4011 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4012 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4013 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4014 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4015 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4016 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4017 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4018 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4019 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4020 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4021 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4022 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4023 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4024 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4025 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4026 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4027 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4028 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4029 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4030 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4031 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4032 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4033 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4034 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4035 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4036 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4037 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4038 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4039 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4040 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4041 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4042 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4043 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4044 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4045 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4046 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4047 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4048 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4049 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4050 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4051 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4052 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4053 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4054 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4055 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4056 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4057 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4058 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4059 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4060 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4061 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4062 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4063 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4064 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4065 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4066 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4067 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4068 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4069 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4070 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4071 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4072 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4073 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4074 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4075 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4076 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4077 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4078 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4079 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4080 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4081 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4082 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4083 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4084 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4085 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4086 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4087 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4088 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4089 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4090 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4091 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4092 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4093 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4094 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4095 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4096 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4097 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4098 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4099 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4100 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4101 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4102 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4103 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4104 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4105 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4106 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4107 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4108 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4109 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4110 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4111 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4112 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4113 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4114 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4115 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4116 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4117 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4118 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4119 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4120 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4121 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4122 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4123 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4124 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4125 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4126 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4127 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4128 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4129 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4130 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4131 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4132 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4133 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4134 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4135 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4136 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4137 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4138 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4139 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4140 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4141 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4142 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4143 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4144 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4145 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4146 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4147 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4148 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4149 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4150 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4151 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4152 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4153 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4154 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4155 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4156 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4157 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4158 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4159 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4160 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4161 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4162 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4163 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4164 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4165 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4166 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4167 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4168 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4169 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4170 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4171 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4172 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4173 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4174 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4175 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4176 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4177 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4178 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4179 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4180 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4181 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4182 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4183 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4184 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4185 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4186 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4187 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4188 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4189 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4190 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4191 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4192 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4193 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4194 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4195 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4196 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4197 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4198 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4199 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4200 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4201 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4202 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4203 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4204 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4205 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4206 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4207 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4208 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4209 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4210 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4211 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4212 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4213 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4214 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4215 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4216 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4217 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4218 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4219 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4220 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4221 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4222 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4223 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4224 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4225 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4226 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4227 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4228 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4229 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4230 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4231 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4232 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4233 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4234 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4235 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4236 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4237 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4238 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4239 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4240 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4241 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4242 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4243 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4244 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4245 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4246 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4247 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4248 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4249 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4250 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4251 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4252 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4253 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4254 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4255 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4256 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4257 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4258 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4259 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4260 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4261 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4262 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4263 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4264 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4265 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4266 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4267 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4268 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4269 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4270 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4271 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4272 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4273 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4274 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4275 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4276 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4277 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4278 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4279 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4280 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4281 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4282 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4283 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4284 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4285 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4286 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4287 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4288 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4289 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4290 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4291 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4292 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4293 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4294 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4295 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4296 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4297 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4298 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4299 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4300 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4301 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4302 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4303 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4304 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4305 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4306 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4307 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4308 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4309 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4310 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4311 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4312 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4313 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4314 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4315 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4316 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4317 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4318 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4319 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4320 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4321 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4322 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4323 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4324 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4325 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4326 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4327 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4328 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4329 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4330 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4331 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4332 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4333 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4334 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4335 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4336 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4337 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4338 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4339 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4340 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4341 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4342 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4343 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4344 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4345 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4346 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4347 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4348 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4349 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4350 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4351 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4352 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4353 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4354 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4355 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4356 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4357 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4358 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4359 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4360 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4361 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4362 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4363 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4364 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4365 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4366 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4367 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4368 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4369 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4370 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4371 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4372 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4373 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4374 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4375 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4376 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4377 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4378 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4379 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4380 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4381 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4382 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4383 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4384 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4385 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4386 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4387 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4388 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4389 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4390 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4391 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4392 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4393 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4394 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4395 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4396 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4397 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4398 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4399 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4400 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4401 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4402 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4403 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4404 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4405 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4406 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4407 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4408 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4409 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4410 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4411 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4412 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4413 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4414 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4415 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4416 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4417 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4418 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4419 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4420 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4421 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4422 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4423 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4424 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4425 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4426 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4427 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4428 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4429 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4430 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4431 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4432 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4433 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4434 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4435 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4436 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4437 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4438 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4439 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4440 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4441
4442 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4443 {
4444     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4445     BOOL ret;
4446     BYTE *buf = NULL;
4447     DWORD size = 0, i;
4448
4449     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4450     {
4451         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4452          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4453          &buf, &size);
4454         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4455          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4456          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4457          GetLastError());
4458     }
4459     /* at a minimum, a CRL must contain an issuer: */
4460     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4461      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4462      &buf, &size);
4463     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4464     if (buf)
4465     {
4466         CRL_INFO *info = (CRL_INFO *)buf;
4467
4468         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4469         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4470          info->cCRLEntry);
4471         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4472          "Wrong issuer size %d\n", info->Issuer.cbData);
4473         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4474          "Unexpected issuer\n");
4475         LocalFree(buf);
4476     }
4477     /* check decoding with an empty CRL entry */
4478     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4479      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4480      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4481     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4482      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4483      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4484      GetLastError());
4485     /* with a real CRL entry */
4486     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4487      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4488      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4489     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4490     if (buf)
4491     {
4492         CRL_INFO *info = (CRL_INFO *)buf;
4493         CRL_ENTRY *entry;
4494
4495         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4496         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4497          info->cCRLEntry);
4498         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4499         entry = info->rgCRLEntry;
4500         ok(entry->SerialNumber.cbData == 1,
4501          "Expected serial number size 1, got %d\n",
4502          entry->SerialNumber.cbData);
4503         ok(*entry->SerialNumber.pbData == *serialNum,
4504          "Expected serial number %d, got %d\n", *serialNum,
4505          *entry->SerialNumber.pbData);
4506         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4507          "Wrong issuer size %d\n", info->Issuer.cbData);
4508         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4509          "Unexpected issuer\n");
4510         LocalFree(buf);
4511     }
4512     /* a real CRL from verisign that has extensions */
4513     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4514      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4515      NULL, &buf, &size);
4516     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4517     if (buf)
4518     {
4519         CRL_INFO *info = (CRL_INFO *)buf;
4520         CRL_ENTRY *entry;
4521
4522         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4523         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4524          info->cCRLEntry);
4525         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4526         entry = info->rgCRLEntry;
4527         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4528          info->cExtension);
4529         LocalFree(buf);
4530     }
4531     /* another real CRL from verisign that has lots of entries */
4532     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4533      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4534      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4535     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4536     if (buf)
4537     {
4538         CRL_INFO *info = (CRL_INFO *)buf;
4539
4540         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4541         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4542          info->cCRLEntry);
4543         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4544          info->cExtension);
4545         LocalFree(buf);
4546     }
4547     /* and finally, with an extension */
4548     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4549      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4550      NULL, &buf, &size);
4551     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4552     if (buf)
4553     {
4554         CRL_INFO *info = (CRL_INFO *)buf;
4555         CRL_ENTRY *entry;
4556
4557         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4558         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4559          info->cCRLEntry);
4560         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4561         entry = info->rgCRLEntry;
4562         ok(entry->SerialNumber.cbData == 1,
4563          "Expected serial number size 1, got %d\n",
4564          entry->SerialNumber.cbData);
4565         ok(*entry->SerialNumber.pbData == *serialNum,
4566          "Expected serial number %d, got %d\n", *serialNum,
4567          *entry->SerialNumber.pbData);
4568         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4569          "Wrong issuer size %d\n", info->Issuer.cbData);
4570         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4571          "Unexpected issuer\n");
4572         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4573          info->cExtension);
4574         LocalFree(buf);
4575     }
4576     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4577      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4578      NULL, &buf, &size);
4579     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4580     if (buf)
4581     {
4582         CRL_INFO *info = (CRL_INFO *)buf;
4583
4584         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4585          info->cExtension);
4586         LocalFree(buf);
4587     }
4588     /* And again, with an issuing dist point */
4589     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4590      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4591      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4592     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4593     if (buf)
4594     {
4595         CRL_INFO *info = (CRL_INFO *)buf;
4596
4597         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4598          info->cExtension);
4599         LocalFree(buf);
4600     }
4601 }
4602
4603 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4604  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4605 static const BYTE encodedUsage[] = {
4606  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4607  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4608  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4609
4610 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4611 {
4612     BOOL ret;
4613     BYTE *buf = NULL;
4614     DWORD size = 0;
4615     CERT_ENHKEY_USAGE usage;
4616
4617     /* Test with empty usage */
4618     usage.cUsageIdentifier = 0;
4619     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4620      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4621     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4622     if (buf)
4623     {
4624         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4625         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4626         LocalFree(buf);
4627     }
4628     /* Test with a few usages */
4629     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4630     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4631     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4632      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4633     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4634     if (buf)
4635     {
4636         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4637         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4638         LocalFree(buf);
4639     }
4640 }
4641
4642 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4643 {
4644     BOOL ret;
4645     LPBYTE buf = NULL;
4646     DWORD size = 0;
4647
4648     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4649      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4650      &buf, &size);
4651     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4652     if (buf)
4653     {
4654         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4655
4656         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4657          "Wrong size %d\n", size);
4658         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4659          usage->cUsageIdentifier);
4660         LocalFree(buf);
4661     }
4662     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4663      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4664      &buf, &size);
4665     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4666     if (buf)
4667     {
4668         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4669         DWORD i;
4670
4671         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4672          "Wrong size %d\n", size);
4673         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4674          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4675         for (i = 0; i < usage->cUsageIdentifier; i++)
4676             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4677              "Expected OID %s, got %s\n", keyUsages[i],
4678              usage->rgpszUsageIdentifier[i]);
4679         LocalFree(buf);
4680     }
4681 }
4682
4683 static BYTE keyId[] = { 1,2,3,4 };
4684 static const BYTE authorityKeyIdWithId[] = {
4685  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4686 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4687  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4688  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4689 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4690
4691 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4692 {
4693     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4694     BOOL ret;
4695     BYTE *buf = NULL;
4696     DWORD size = 0;
4697
4698     /* Test with empty id */
4699     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4700      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4701     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4702     if (buf)
4703     {
4704         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4705         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4706         LocalFree(buf);
4707     }
4708     /* With just a key id */
4709     info.KeyId.cbData = sizeof(keyId);
4710     info.KeyId.pbData = keyId;
4711     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4712      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4713     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4714     if (buf)
4715     {
4716         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4717         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4718         LocalFree(buf);
4719     }
4720     /* With just an issuer */
4721     info.KeyId.cbData = 0;
4722     info.CertIssuer.cbData = sizeof(encodedCommonName);
4723     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4724     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4725      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4726     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4727     if (buf)
4728     {
4729         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4730          size);
4731         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4732         LocalFree(buf);
4733     }
4734     /* With just a serial number */
4735     info.CertIssuer.cbData = 0;
4736     info.CertSerialNumber.cbData = sizeof(serialNum);
4737     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4738     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4739      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4740     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4741     if (buf)
4742     {
4743         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4744          size);
4745         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4746         LocalFree(buf);
4747     }
4748 }
4749
4750 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4751 {
4752     BOOL ret;
4753     LPBYTE buf = NULL;
4754     DWORD size = 0;
4755
4756     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4757      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4758      &buf, &size);
4759     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4760     if (buf)
4761     {
4762         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4763
4764         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4765          size);
4766         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4767         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4768         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4769         LocalFree(buf);
4770     }
4771     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4772      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4773      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4774     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4775     if (buf)
4776     {
4777         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4778
4779         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4780          size);
4781         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4782         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4783          "Unexpected key id\n");
4784         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4785         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4786         LocalFree(buf);
4787     }
4788     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4789      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4790      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4791     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4792     if (buf)
4793     {
4794         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4795
4796         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4797          size);
4798         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4799         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4800          "Unexpected issuer len\n");
4801         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4802          sizeof(encodedCommonName)), "Unexpected issuer\n");
4803         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4804         LocalFree(buf);
4805     }
4806     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4807      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4808      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4809     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4810     if (buf)
4811     {
4812         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4813
4814         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4815          size);
4816         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4817         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4818         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4819          "Unexpected serial number len\n");
4820         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4821          "Unexpected serial number\n");
4822         LocalFree(buf);
4823     }
4824 }
4825
4826 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4827  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4828  0x6f,0x72,0x67 };
4829
4830 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4831 {
4832     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4833     CERT_ALT_NAME_ENTRY entry = { 0 };
4834     BOOL ret;
4835     BYTE *buf = NULL;
4836     DWORD size = 0;
4837
4838     /* Test with empty id */
4839     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4840      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4841     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4842     if (buf)
4843     {
4844         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4845         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4846         LocalFree(buf);
4847     }
4848     /* With just a key id */
4849     info.KeyId.cbData = sizeof(keyId);
4850     info.KeyId.pbData = keyId;
4851     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4852      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4853     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4854     if (buf)
4855     {
4856         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4857          size);
4858         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4859         LocalFree(buf);
4860     }
4861     /* With a bogus issuer name */
4862     info.KeyId.cbData = 0;
4863     info.AuthorityCertIssuer.cAltEntry = 1;
4864     info.AuthorityCertIssuer.rgAltEntry = &entry;
4865     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4866      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4867     ok(!ret && GetLastError() == E_INVALIDARG,
4868      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4869     /* With an issuer name */
4870     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4871     U(entry).pwszURL = (LPWSTR)url;
4872     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4873      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4874     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4875     if (buf)
4876     {
4877         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4878          size);
4879         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4880          "Unexpected value\n");
4881         LocalFree(buf);
4882     }
4883     /* With just a serial number */
4884     info.AuthorityCertIssuer.cAltEntry = 0;
4885     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4886     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4887     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4888      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4889     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4890     if (buf)
4891     {
4892         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4893          size);
4894         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4895         LocalFree(buf);
4896     }
4897 }
4898
4899 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4900 {
4901     BOOL ret;
4902     LPBYTE buf = NULL;
4903     DWORD size = 0;
4904
4905     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4906      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4907      &buf, &size);
4908     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4909     if (buf)
4910     {
4911         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4912
4913         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4914          size);
4915         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4916         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4917          "Expected no issuer name entries\n");
4918         ok(info->AuthorityCertSerialNumber.cbData == 0,
4919          "Expected no serial number\n");
4920         LocalFree(buf);
4921     }
4922     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4923      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4924      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4925     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4926     if (buf)
4927     {
4928         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4929
4930         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4931          size);
4932         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4933         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4934          "Unexpected key id\n");
4935         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4936          "Expected no issuer name entries\n");
4937         ok(info->AuthorityCertSerialNumber.cbData == 0,
4938          "Expected no serial number\n");
4939         LocalFree(buf);
4940     }
4941     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4942      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4943      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4944     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4945     if (buf)
4946     {
4947         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4948
4949         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4950          size);
4951         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4952         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4953          "Expected 1 issuer entry, got %d\n",
4954          info->AuthorityCertIssuer.cAltEntry);
4955         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4956          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4957          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4958         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4959          url), "Unexpected URL\n");
4960         ok(info->AuthorityCertSerialNumber.cbData == 0,
4961          "Expected no serial number\n");
4962         LocalFree(buf);
4963     }
4964     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4965      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4966      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4967     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4968     if (buf)
4969     {
4970         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4971
4972         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4973          size);
4974         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4975         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4976          "Expected no issuer name entries\n");
4977         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4978          "Unexpected serial number len\n");
4979         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4980          sizeof(serialNum)), "Unexpected serial number\n");
4981         LocalFree(buf);
4982     }
4983 }
4984
4985 static const BYTE authorityInfoAccessWithUrl[] = {
4986 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4987 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4988 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4989 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4990 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4991 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4992
4993 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4994 {
4995     static char oid1[] = "1.2.3";
4996     static char oid2[] = "1.5.6";
4997     BOOL ret;
4998     BYTE *buf = NULL;
4999     DWORD size = 0;
5000     CERT_ACCESS_DESCRIPTION accessDescription[2];
5001     CERT_AUTHORITY_INFO_ACCESS aia;
5002
5003     memset(accessDescription, 0, sizeof(accessDescription));
5004     aia.cAccDescr = 0;
5005     aia.rgAccDescr = NULL;
5006     /* Having no access descriptions is allowed */
5007     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5008      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5009     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5010     if (buf)
5011     {
5012         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5013         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5014         LocalFree(buf);
5015         buf = NULL;
5016     }
5017     /* It can't have an empty access method */
5018     aia.cAccDescr = 1;
5019     aia.rgAccDescr = accessDescription;
5020     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5021      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5022     ok(!ret && (GetLastError() == E_INVALIDARG ||
5023      GetLastError() == OSS_LIMITED /* Win9x */),
5024      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5025     /* It can't have an empty location */
5026     accessDescription[0].pszAccessMethod = oid1;
5027     SetLastError(0xdeadbeef);
5028     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5029      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5030     ok(!ret && GetLastError() == E_INVALIDARG,
5031      "expected E_INVALIDARG, got %08x\n", GetLastError());
5032     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5033     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5034     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5035      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5036     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5037     if (buf)
5038     {
5039         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5040          size);
5041         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5042          "unexpected value\n");
5043         LocalFree(buf);
5044         buf = NULL;
5045     }
5046     accessDescription[1].pszAccessMethod = oid2;
5047     accessDescription[1].AccessLocation.dwAltNameChoice =
5048      CERT_ALT_NAME_IP_ADDRESS;
5049     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5050      sizeof(encodedIPAddr);
5051     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5052      (LPBYTE)encodedIPAddr;
5053     aia.cAccDescr = 2;
5054     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5055      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5056     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5057     if (buf)
5058     {
5059         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5060          "unexpected size %d\n", size);
5061         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5062          "unexpected value\n");
5063         LocalFree(buf);
5064         buf = NULL;
5065     }
5066 }
5067
5068 static void compareAuthorityInfoAccess(LPCSTR header,
5069  const CERT_AUTHORITY_INFO_ACCESS *expected,
5070  const CERT_AUTHORITY_INFO_ACCESS *got)
5071 {
5072     DWORD i;
5073
5074     ok(expected->cAccDescr == got->cAccDescr,
5075      "%s: expected %d access descriptions, got %d\n", header,
5076      expected->cAccDescr, got->cAccDescr);
5077     for (i = 0; i < expected->cAccDescr; i++)
5078     {
5079         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5080          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5081          header, i, expected->rgAccDescr[i].pszAccessMethod,
5082          got->rgAccDescr[i].pszAccessMethod);
5083         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5084          &got->rgAccDescr[i].AccessLocation);
5085     }
5086 }
5087
5088 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5089 {
5090     static char oid1[] = "1.2.3";
5091     static char oid2[] = "1.5.6";
5092     BOOL ret;
5093     LPBYTE buf = NULL;
5094     DWORD size = 0;
5095
5096     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5097      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5098      &buf, &size);
5099     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5100     if (buf)
5101     {
5102         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5103
5104         compareAuthorityInfoAccess("empty AIA", &aia,
5105          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5106         LocalFree(buf);
5107         buf = NULL;
5108     }
5109     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5110      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5111      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5112     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5113     if (buf)
5114     {
5115         CERT_ACCESS_DESCRIPTION accessDescription;
5116         CERT_AUTHORITY_INFO_ACCESS aia;
5117
5118         accessDescription.pszAccessMethod = oid1;
5119         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5120         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5121         aia.cAccDescr = 1;
5122         aia.rgAccDescr = &accessDescription;
5123         compareAuthorityInfoAccess("AIA with URL", &aia,
5124          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5125         LocalFree(buf);
5126         buf = NULL;
5127     }
5128     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5129      authorityInfoAccessWithUrlAndIPAddr,
5130      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5131      NULL, &buf, &size);
5132     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5133     if (buf)
5134     {
5135         CERT_ACCESS_DESCRIPTION accessDescription[2];
5136         CERT_AUTHORITY_INFO_ACCESS aia;
5137
5138         accessDescription[0].pszAccessMethod = oid1;
5139         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5140         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5141         accessDescription[1].pszAccessMethod = oid2;
5142         accessDescription[1].AccessLocation.dwAltNameChoice =
5143          CERT_ALT_NAME_IP_ADDRESS;
5144         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5145          sizeof(encodedIPAddr);
5146         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5147          (LPBYTE)encodedIPAddr;
5148         aia.cAccDescr = 2;
5149         aia.rgAccDescr = accessDescription;
5150         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5151          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5152         LocalFree(buf);
5153         buf = NULL;
5154     }
5155 }
5156
5157 static const BYTE emptyCTL[] = {
5158 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5159 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5160 static const BYTE emptyCTLWithVersion1[] = {
5161 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5162 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5163 static const BYTE ctlWithUsageIdentifier[] = {
5164 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5165 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5166 static const BYTE ctlWithListIdentifier[] = {
5167 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5168 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5169 static const BYTE ctlWithSequenceNumber[] = {
5170 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5171 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5172 static const BYTE ctlWithThisUpdate[] = {
5173 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5174 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5175 static const BYTE ctlWithThisAndNextUpdate[] = {
5176 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5177 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5178 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5179 static const BYTE ctlWithAlgId[] = {
5180 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5181 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5182 static const BYTE ctlWithBogusEntry[] = {
5183 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5184 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5185 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5186 static const BYTE ctlWithOneEntry[] = {
5187 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5188 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5189 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5190 static const BYTE ctlWithTwoEntries[] = {
5191 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5192 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5193 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5194 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5195 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5196
5197 static void test_encodeCTL(DWORD dwEncoding)
5198 {
5199     static char oid1[] = "1.2.3";
5200     static char oid2[] = "1.5.6";
5201     char *pOid1 = oid1;
5202     BOOL ret;
5203     BYTE *buf = NULL;
5204     DWORD size = 0;
5205     CTL_INFO info;
5206     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5207     CTL_ENTRY ctlEntry[2];
5208     CRYPT_ATTRIBUTE attr1, attr2;
5209     CRYPT_ATTR_BLOB value1, value2;
5210
5211     memset(&info, 0, sizeof(info));
5212     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5213      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5214     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5215     if (buf)
5216     {
5217         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5218         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5219         LocalFree(buf);
5220         buf = NULL;
5221     }
5222     info.dwVersion = 1;
5223     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5224      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5225     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5226     if (buf)
5227     {
5228         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5229         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5230         LocalFree(buf);
5231         buf = NULL;
5232     }
5233     info.dwVersion = 0;
5234     info.SubjectUsage.cUsageIdentifier = 1;
5235     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5236     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5237      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5238     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5239     if (buf)
5240     {
5241         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5242          size);
5243         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5244         LocalFree(buf);
5245         buf = NULL;
5246     }
5247     info.SubjectUsage.cUsageIdentifier = 0;
5248     info.ListIdentifier.cbData = sizeof(serialNum);
5249     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5250     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5251      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5252     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5253     if (buf)
5254     {
5255         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5256         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5257         LocalFree(buf);
5258         buf = NULL;
5259     }
5260     info.ListIdentifier.cbData = 0;
5261     info.SequenceNumber.cbData = sizeof(serialNum);
5262     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5263     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5264      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5265     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5266     if (buf)
5267     {
5268         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5269          size);
5270         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5271         LocalFree(buf);
5272         buf = NULL;
5273     }
5274     info.SequenceNumber.cbData = 0;
5275     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5276     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5277      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5278     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5279     if (buf)
5280     {
5281         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5282         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5283         LocalFree(buf);
5284         buf = NULL;
5285     }
5286     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5287     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5288      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5289     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5290     if (buf)
5291     {
5292         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5293          size);
5294         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5295         LocalFree(buf);
5296         buf = NULL;
5297     }
5298     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5299     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5300     info.SubjectAlgorithm.pszObjId = oid2;
5301     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5302      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5303     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5304     if (buf)
5305     {
5306         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5307         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5308         LocalFree(buf);
5309         buf = NULL;
5310     }
5311     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5312      * (see tests below) but it'll encode fine.
5313      */
5314     info.SubjectAlgorithm.pszObjId = NULL;
5315     value1.cbData = sizeof(serialNum);
5316     value1.pbData = (LPBYTE)serialNum;
5317     attr1.pszObjId = oid1;
5318     attr1.cValue = 1;
5319     attr1.rgValue = &value1;
5320     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5321     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5322     ctlEntry[0].cAttribute = 1;
5323     ctlEntry[0].rgAttribute = &attr1;
5324     info.cCTLEntry = 1;
5325     info.rgCTLEntry = ctlEntry;
5326     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5327      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5328     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5329     if (buf)
5330     {
5331         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5332         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5333         LocalFree(buf);
5334         buf = NULL;
5335     }
5336     value1.cbData = sizeof(emptySequence);
5337     value1.pbData = (LPBYTE)emptySequence;
5338     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5339      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5340     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5341     if (buf)
5342     {
5343         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5344         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5345         LocalFree(buf);
5346         buf = NULL;
5347     }
5348     value2.cbData = sizeof(encodedIPAddr);
5349     value2.pbData = (LPBYTE)encodedIPAddr;
5350     attr2.pszObjId = oid2;
5351     attr2.cValue = 1;
5352     attr2.rgValue = &value2;
5353     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5354     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5355     ctlEntry[1].cAttribute = 1;
5356     ctlEntry[1].rgAttribute = &attr2;
5357     info.cCTLEntry = 2;
5358     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5359      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5360     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5361     if (buf)
5362     {
5363         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5364         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5365         LocalFree(buf);
5366         buf = NULL;
5367     }
5368 }
5369
5370 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5371  const CTL_INFO *got)
5372 {
5373     DWORD i, j, k;
5374
5375     ok(expected->dwVersion == got->dwVersion,
5376      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5377      got->dwVersion);
5378     ok(expected->SubjectUsage.cUsageIdentifier ==
5379      got->SubjectUsage.cUsageIdentifier,
5380      "%s: expected %d usage identifiers, got %d\n", header,
5381      expected->SubjectUsage.cUsageIdentifier,
5382      got->SubjectUsage.cUsageIdentifier);
5383     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5384         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5385          got->SubjectUsage.rgpszUsageIdentifier[i]),
5386          "%s[%d]: expected %s, got %s\n", header, i,
5387          expected->SubjectUsage.rgpszUsageIdentifier[i],
5388          got->SubjectUsage.rgpszUsageIdentifier[i]);
5389     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5390      "%s: expected list identifier of %d bytes, got %d\n", header,
5391      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5392     if (expected->ListIdentifier.cbData)
5393         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5394          expected->ListIdentifier.cbData),
5395          "%s: unexpected list identifier value\n", header);
5396     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5397      "%s: expected sequence number of %d bytes, got %d\n", header,
5398      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5399     if (expected->SequenceNumber.cbData)
5400         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5401          expected->SequenceNumber.cbData),
5402          "%s: unexpected sequence number value\n", header);
5403     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5404      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5405      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5406      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5407     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5408      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5409      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5410      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5411     if (expected->SubjectAlgorithm.pszObjId &&
5412      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5413         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5414          expected->SubjectAlgorithm.pszObjId);
5415     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5416         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5417          got->SubjectAlgorithm.pszObjId),
5418          "%s: expected subject algorithm %s, got %s\n", header,
5419          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5420     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5421      got->SubjectAlgorithm.Parameters.cbData,
5422      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5423      expected->SubjectAlgorithm.Parameters.cbData,
5424      got->SubjectAlgorithm.Parameters.cbData);
5425     if (expected->SubjectAlgorithm.Parameters.cbData)
5426         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5427          got->SubjectAlgorithm.Parameters.pbData,
5428          expected->SubjectAlgorithm.Parameters.cbData),
5429          "%s: unexpected subject algorithm parameter value\n", header);
5430     ok(expected->cCTLEntry == got->cCTLEntry,
5431      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5432      got->cCTLEntry);
5433     for (i = 0; i < expected->cCTLEntry; i++)
5434     {
5435         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5436          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5437          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5438          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5439          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5440         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5441             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5442              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5443              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5444              "%s[%d]: unexpected subject identifier value\n",
5445              header, i);
5446         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5447         {
5448             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5449              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5450              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5451              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5452              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5453             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5454             {
5455                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5456                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5457                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5458                  header, i, j, k,
5459                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5460                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5461                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5462                     ok(!memcmp(
5463                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5464                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5465                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5466                      "%s[%d][%d][%d]: unexpected value\n",
5467                      header, i, j, k);
5468             }
5469         }
5470     }
5471     ok(expected->cExtension == got->cExtension,
5472      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5473      got->cExtension);
5474     for (i = 0; i < expected->cExtension; i++)
5475     {
5476         ok(!strcmp(expected->rgExtension[i].pszObjId,
5477          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5478          header, i, expected->rgExtension[i].pszObjId,
5479          got->rgExtension[i].pszObjId);
5480         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5481          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5482          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5483         ok(expected->rgExtension[i].Value.cbData ==
5484          got->rgExtension[i].Value.cbData,
5485          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5486          header, i, expected->rgExtension[i].Value.cbData,
5487          got->rgExtension[i].Value.cbData);
5488         if (expected->rgExtension[i].Value.cbData)
5489             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5490              got->rgExtension[i].Value.pbData,
5491              expected->rgExtension[i].Value.cbData),
5492              "%s[%d]: unexpected extension value\n", header, i);
5493     }
5494 }
5495
5496 static const BYTE signedCTL[] = {
5497 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5498 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5499 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5500 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5501 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5502 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5503 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5504 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5505 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5506 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5507 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5508 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5509 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5510 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5511 static const BYTE signedCTLWithCTLInnerContent[] = {
5512 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5513 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5514 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5515 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5516 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5517 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5518 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5519 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5520 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5521 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5522 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5523 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5524 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5525 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5526 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5527 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5528 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5529 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5530 0x57,0x6c,0x0b,0x47,0xb8 };
5531
5532 static void test_decodeCTL(DWORD dwEncoding)
5533 {
5534     static char oid1[] = "1.2.3";
5535     static char oid2[] = "1.5.6";
5536     static BYTE nullData[] = { 5,0 };
5537     char *pOid1 = oid1;
5538     BOOL ret;
5539     BYTE *buf = NULL;
5540     DWORD size = 0;
5541     CTL_INFO info;
5542     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5543     CTL_ENTRY ctlEntry[2];
5544     CRYPT_ATTRIBUTE attr1, attr2;
5545     CRYPT_ATTR_BLOB value1, value2;
5546
5547     memset(&info, 0, sizeof(info));
5548     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5549      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5550     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5551     if (buf)
5552     {
5553         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5554         LocalFree(buf);
5555         buf = NULL;
5556     }
5557     info.dwVersion = 1;
5558     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5559      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5560      &size);
5561     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5562     if (buf)
5563     {
5564         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5565         LocalFree(buf);
5566         buf = NULL;
5567     }
5568     info.dwVersion = 0;
5569     info.SubjectUsage.cUsageIdentifier = 1;
5570     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5571     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5572      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5573      &buf, &size);
5574     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5575     if (buf)
5576     {
5577         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5578         LocalFree(buf);
5579         buf = NULL;
5580     }
5581     info.SubjectUsage.cUsageIdentifier = 0;
5582     info.ListIdentifier.cbData = sizeof(serialNum);
5583     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5584     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5585      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5586     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5587     if (buf)
5588     {
5589         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5590         LocalFree(buf);
5591         buf = NULL;
5592     }
5593     info.ListIdentifier.cbData = 0;
5594     info.SequenceNumber.cbData = sizeof(serialNum);
5595     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5596     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5597      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5599     if (buf)
5600     {
5601         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5602         LocalFree(buf);
5603         buf = NULL;
5604     }
5605     info.SequenceNumber.cbData = 0;
5606     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5607     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5608      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5609     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5610     if (buf)
5611     {
5612         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5613         LocalFree(buf);
5614         buf = NULL;
5615     }
5616     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5617     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5618      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5619      &buf, &size);
5620     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5621     if (buf)
5622     {
5623         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5624         LocalFree(buf);
5625         buf = NULL;
5626     }
5627     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5628     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5629     info.SubjectAlgorithm.pszObjId = oid2;
5630     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5631     info.SubjectAlgorithm.Parameters.pbData = nullData;
5632     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5633      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5634     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5635     if (buf)
5636     {
5637         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5638         LocalFree(buf);
5639         buf = NULL;
5640     }
5641     SetLastError(0xdeadbeef);
5642     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5643      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5644     ok(!ret &&
5645      (GetLastError() == CRYPT_E_ASN1_EOD ||
5646       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5647       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5648      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5649      GetLastError());
5650     info.SubjectAlgorithm.Parameters.cbData = 0;
5651     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5652     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5653     info.SubjectAlgorithm.pszObjId = oid2;
5654     info.SubjectAlgorithm.pszObjId = NULL;
5655     value1.cbData = sizeof(emptySequence);
5656     value1.pbData = (LPBYTE)emptySequence;
5657     attr1.pszObjId = oid1;
5658     attr1.cValue = 1;
5659     attr1.rgValue = &value1;
5660     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5661     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5662     ctlEntry[0].cAttribute = 1;
5663     ctlEntry[0].rgAttribute = &attr1;
5664     info.cCTLEntry = 1;
5665     info.rgCTLEntry = ctlEntry;
5666     SetLastError(0xdeadbeef);
5667     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5668      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5669     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5670     if (buf)
5671     {
5672         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5673         LocalFree(buf);
5674         buf = NULL;
5675     }
5676     value2.cbData = sizeof(encodedIPAddr);
5677     value2.pbData = (LPBYTE)encodedIPAddr;
5678     attr2.pszObjId = oid2;
5679     attr2.cValue = 1;
5680     attr2.rgValue = &value2;
5681     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5682     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5683     ctlEntry[1].cAttribute = 1;
5684     ctlEntry[1].rgAttribute = &attr2;
5685     info.cCTLEntry = 2;
5686     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5687      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5688     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5689     if (buf)
5690     {
5691         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5692         LocalFree(buf);
5693         buf = NULL;
5694     }
5695     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5696     SetLastError(0xdeadbeef);
5697     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5698      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5699     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5700      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5701      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5702      GetLastError());
5703     SetLastError(0xdeadbeef);
5704     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5705      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5706      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5707     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5708      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5709      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5710      GetLastError());
5711 }
5712
5713 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5714 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5715  0x03,0,0,0,0,0,0 };
5716 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5717  0xa0,0x01,0x01 };
5718 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5719  0x03,0x02,0x01,0x01 };
5720 static BYTE bogusDER[] = { 1 };
5721
5722 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5723 {
5724     BOOL ret;
5725     BYTE *buf = NULL;
5726     DWORD size = 0;
5727     CRYPT_CONTENT_INFO info = { 0 };
5728     char oid1[] = "1.2.3";
5729
5730     if (0)
5731     {
5732         /* Crashes on win9x */
5733         SetLastError(0xdeadbeef);
5734         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5735          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5736         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5737          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5738     }
5739     SetLastError(0xdeadbeef);
5740     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5741      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5742     ok(!ret && (GetLastError() == E_INVALIDARG ||
5743      GetLastError() == OSS_LIMITED /* Win9x */),
5744      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5745     info.pszObjId = oid1;
5746     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5747      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5748     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5749     if (buf)
5750     {
5751         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5752         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5753         LocalFree(buf);
5754     }
5755     info.Content.pbData = bogusDER;
5756     info.Content.cbData = sizeof(bogusDER);
5757     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5758      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5759     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5760     if (buf)
5761     {
5762         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5763         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5764         LocalFree(buf);
5765     }
5766     info.Content.pbData = (BYTE *)ints[0].encoded;
5767     info.Content.cbData = ints[0].encoded[1] + 2;
5768     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5769      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5770     if (buf)
5771     {
5772         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5773         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5774         LocalFree(buf);
5775     }
5776 }
5777
5778 static const BYTE indefiniteSignedPKCSContent[] = {
5779 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5780 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5781 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5782 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5783 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5784 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5785 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5786 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5787 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5788 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5789 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5790 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5791 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5792 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5793 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5794 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5795 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5796 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5797 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5798 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5799 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5800 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5801 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5802 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5803 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5804 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5805 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5806 0x00,0x00,0x00,0x00,0x00,0x00 };
5807
5808 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5809 {
5810     BOOL ret;
5811     LPBYTE buf = NULL;
5812     DWORD size = 0;
5813     CRYPT_CONTENT_INFO *info;
5814
5815     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5816      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5817      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5818     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5819     if (buf)
5820     {
5821         info = (CRYPT_CONTENT_INFO *)buf;
5822
5823         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5824          info->pszObjId);
5825         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5826          info->Content.cbData);
5827         LocalFree(buf);
5828     }
5829     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5830      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5831      0, NULL, NULL, &size);
5832     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5833     SetLastError(0xdeadbeef);
5834     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5835      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5836      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5837     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5838      * I doubt an app depends on that.
5839      */
5840     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5841      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5842      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5843      GetLastError());
5844     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5845      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5846      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5847     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5848     if (buf)
5849     {
5850         info = (CRYPT_CONTENT_INFO *)buf;
5851
5852         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5853          info->pszObjId);
5854         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5855          "Unexpected size %d\n", info->Content.cbData);
5856         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5857          info->Content.cbData), "Unexpected value\n");
5858         LocalFree(buf);
5859     }
5860     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5861      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5862      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5863     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5864     if (buf)
5865     {
5866         info = (CRYPT_CONTENT_INFO *)buf;
5867
5868         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5869          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5870         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5871          info->Content.cbData);
5872         LocalFree(buf);
5873     }
5874 }
5875
5876 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5877  0x00 };
5878 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5879  0x01 };
5880 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5881  0x02,0x01,0x01 };
5882
5883 static void test_encodePKCSAttribute(DWORD dwEncoding)
5884 {
5885     CRYPT_ATTRIBUTE attr = { 0 };
5886     BOOL ret;
5887     LPBYTE buf = NULL;
5888     DWORD size = 0;
5889     CRYPT_ATTR_BLOB blob;
5890     char oid[] = "1.2.3";
5891
5892     if (0)
5893     {
5894         /* Crashes on win9x */
5895         SetLastError(0xdeadbeef);
5896         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5897          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5898         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5899          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5900     }
5901     SetLastError(0xdeadbeef);
5902     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5903      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5904     ok(!ret && (GetLastError() == E_INVALIDARG ||
5905      GetLastError() == OSS_LIMITED /* Win9x */),
5906      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5907     attr.pszObjId = oid;
5908     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5909      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5910     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5911     if (buf)
5912     {
5913         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5914         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5915         LocalFree(buf);
5916     }
5917     blob.cbData = sizeof(bogusDER);
5918     blob.pbData = bogusDER;
5919     attr.cValue = 1;
5920     attr.rgValue = &blob;
5921     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5922      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5923     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5924     if (buf)
5925     {
5926         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5927         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5928         LocalFree(buf);
5929     }
5930     blob.pbData = (BYTE *)ints[0].encoded;
5931     blob.cbData = ints[0].encoded[1] + 2;
5932     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5933      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5934     if (buf)
5935     {
5936         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5937         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5938         LocalFree(buf);
5939     }
5940 }
5941
5942 static void test_decodePKCSAttribute(DWORD dwEncoding)
5943 {
5944     BOOL ret;
5945     LPBYTE buf = NULL;
5946     DWORD size = 0;
5947     CRYPT_ATTRIBUTE *attr;
5948
5949     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5950      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5951      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5952     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5953     if (buf)
5954     {
5955         attr = (CRYPT_ATTRIBUTE *)buf;
5956
5957         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5958          attr->pszObjId);
5959         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5960         LocalFree(buf);
5961     }
5962     SetLastError(0xdeadbeef);
5963     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5964      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5965      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5966     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5967      * I doubt an app depends on that.
5968      */
5969     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5970      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5971      GetLastError() == OSS_MORE_INPUT /* Win9x */),
5972      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5973      GetLastError());
5974     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5975      intPKCSAttr, sizeof(intPKCSAttr),
5976      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5977     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5978     if (buf)
5979     {
5980         attr = (CRYPT_ATTRIBUTE *)buf;
5981
5982         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5983          attr->pszObjId);
5984         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5985         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5986          "Unexpected size %d\n", attr->rgValue[0].cbData);
5987         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5988          attr->rgValue[0].cbData), "Unexpected value\n");
5989         LocalFree(buf);
5990     }
5991 }
5992
5993 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5994 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5995  0x2a,0x03,0x31,0x00 };
5996 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5997  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5998
5999 static void test_encodePKCSAttributes(DWORD dwEncoding)
6000 {
6001     CRYPT_ATTRIBUTES attributes = { 0 };
6002     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6003     CRYPT_ATTR_BLOB blob;
6004     BOOL ret;
6005     LPBYTE buf = NULL;
6006     DWORD size = 0;
6007     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6008
6009     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6010      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6011     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6012     if (buf)
6013     {
6014         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6015         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6016         LocalFree(buf);
6017     }
6018     attributes.cAttr = 1;
6019     attributes.rgAttr = attr;
6020     SetLastError(0xdeadbeef);
6021     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6022      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6023     ok(!ret && (GetLastError() == E_INVALIDARG ||
6024      GetLastError() == OSS_LIMITED /* Win9x */),
6025      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6026     attr[0].pszObjId = oid1;
6027     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6028      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6029     if (buf)
6030     {
6031         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6032         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6033         LocalFree(buf);
6034     }
6035     attr[1].pszObjId = oid2;
6036     attr[1].cValue = 1;
6037     attr[1].rgValue = &blob;
6038     blob.pbData = (BYTE *)ints[0].encoded;
6039     blob.cbData = ints[0].encoded[1] + 2;
6040     attributes.cAttr = 2;
6041     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6042      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6043     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6044     if (buf)
6045     {
6046         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6047         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6048         LocalFree(buf);
6049     }
6050 }
6051
6052 static void test_decodePKCSAttributes(DWORD dwEncoding)
6053 {
6054     BOOL ret;
6055     LPBYTE buf = NULL;
6056     DWORD size = 0;
6057     CRYPT_ATTRIBUTES *attributes;
6058
6059     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6060      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6061      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6062     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6063     if (buf)
6064     {
6065         attributes = (CRYPT_ATTRIBUTES *)buf;
6066         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6067          attributes->cAttr);
6068         LocalFree(buf);
6069     }
6070     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6071      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6072      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6073     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6074     if (buf)
6075     {
6076         attributes = (CRYPT_ATTRIBUTES *)buf;
6077         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6078          attributes->cAttr);
6079         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6080          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6081         ok(attributes->rgAttr[0].cValue == 0,
6082          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6083         LocalFree(buf);
6084     }
6085     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6086      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6087      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6088     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6089     if (buf)
6090     {
6091         attributes = (CRYPT_ATTRIBUTES *)buf;
6092         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6093          attributes->cAttr);
6094         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6095          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6096         ok(attributes->rgAttr[0].cValue == 0,
6097          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6098         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6099          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6100         ok(attributes->rgAttr[1].cValue == 1,
6101          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6102         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6103          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6104         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6105          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6106         LocalFree(buf);
6107     }
6108 }
6109
6110 static const BYTE singleCapability[] = {
6111 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6112 static const BYTE twoCapabilities[] = {
6113 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6114 static const BYTE singleCapabilitywithNULL[] = {
6115 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6116
6117 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6118 {
6119     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6120     BOOL ret;
6121     LPBYTE buf = NULL;
6122     DWORD size = 0;
6123     CRYPT_SMIME_CAPABILITY capability[2];
6124     CRYPT_SMIME_CAPABILITIES capabilities;
6125
6126     /* An empty capabilities is allowed */
6127     capabilities.cCapability = 0;
6128     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6129      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6130     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6131     if (buf)
6132     {
6133         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6134         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6135         LocalFree(buf);
6136     }
6137     /* A non-empty capabilities with an empty capability (lacking an OID) is
6138      * not allowed
6139      */
6140     capability[0].pszObjId = NULL;
6141     capability[0].Parameters.cbData = 0;
6142     capabilities.cCapability = 1;
6143     capabilities.rgCapability = capability;
6144     SetLastError(0xdeadbeef);
6145     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6146      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6147     ok(!ret && (GetLastError() == E_INVALIDARG ||
6148      GetLastError() == OSS_LIMITED /* Win9x */),
6149      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6150     capability[0].pszObjId = oid1;
6151     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6152      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6153     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6154     if (buf)
6155     {
6156         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6157         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6158         LocalFree(buf);
6159     }
6160     capability[1].pszObjId = oid2;
6161     capability[1].Parameters.cbData = 0;
6162     capabilities.cCapability = 2;
6163     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6164      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6165     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6166     if (buf)
6167     {
6168         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6169         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6170         LocalFree(buf);
6171     }
6172 }
6173
6174 static void compareSMimeCapabilities(LPCSTR header,
6175  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6176 {
6177     DWORD i;
6178
6179     ok(got->cCapability == expected->cCapability,
6180      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6181      got->cCapability);
6182     for (i = 0; i < expected->cCapability; i++)
6183     {
6184         ok(!strcmp(expected->rgCapability[i].pszObjId,
6185          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6186          header, i, expected->rgCapability[i].pszObjId,
6187          got->rgCapability[i].pszObjId);
6188         ok(expected->rgCapability[i].Parameters.cbData ==
6189          got->rgCapability[i].Parameters.cbData,
6190          "%s[%d]: expected %d bytes, got %d\n", header, i,
6191          expected->rgCapability[i].Parameters.cbData,
6192          got->rgCapability[i].Parameters.cbData);
6193         if (expected->rgCapability[i].Parameters.cbData)
6194             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6195              got->rgCapability[i].Parameters.pbData,
6196              expected->rgCapability[i].Parameters.cbData),
6197              "%s[%d]: unexpected value\n", header, i);
6198     }
6199 }
6200
6201 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6202 {
6203     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6204     BOOL ret;
6205     DWORD size = 0;
6206     CRYPT_SMIME_CAPABILITY capability[2];
6207     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6208
6209     SetLastError(0xdeadbeef);
6210     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6211      emptySequence, sizeof(emptySequence),
6212      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6213     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6214     if (ret)
6215     {
6216         capabilities.cCapability = 0;
6217         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6218         LocalFree(ptr);
6219     }
6220     SetLastError(0xdeadbeef);
6221     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6222      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6223      &ptr, &size);
6224     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6225     if (ret)
6226     {
6227         capability[0].pszObjId = oid1;
6228         capability[0].Parameters.cbData = 0;
6229         capabilities.cCapability = 1;
6230         capabilities.rgCapability = capability;
6231         compareSMimeCapabilities("single capability", &capabilities, ptr);
6232         LocalFree(ptr);
6233     }
6234     SetLastError(0xdeadbeef);
6235     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6236      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6237      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6238     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6239     if (ret)
6240     {
6241         BYTE NULLparam[] = {0x05, 0x00};
6242         capability[0].pszObjId = oid1;
6243         capability[0].Parameters.cbData = 2;
6244         capability[0].Parameters.pbData = NULLparam;
6245         capabilities.cCapability = 1;
6246         capabilities.rgCapability = capability;
6247         compareSMimeCapabilities("single capability with NULL", &capabilities,
6248          ptr);
6249         LocalFree(ptr);
6250     }
6251     SetLastError(0xdeadbeef);
6252     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6253     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6254     &ptr, &size);
6255     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6256     if (ret)
6257     {
6258         capability[0].Parameters.cbData = 0;
6259         capability[1].pszObjId = oid2;
6260         capability[1].Parameters.cbData = 0;
6261         capabilities.cCapability = 2;
6262         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6263         LocalFree(ptr);
6264     }
6265 }
6266
6267 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6268  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6269  0x67 };
6270 static const BYTE minimalPKCSSigner[] = {
6271  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6272  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6273  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6274 static const BYTE PKCSSignerWithSerial[] = {
6275  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6276  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6277  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6278  0x00 };
6279 static const BYTE PKCSSignerWithHashAlgo[] = {
6280  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6281  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6282  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6283  0x00,0x04,0x00 };
6284 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6285  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6286  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6287  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6288  0x06,0x05,0x00,0x04,0x00 };
6289 static const BYTE PKCSSignerWithHash[] = {
6290  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6291  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6292  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6293  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6294  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6295 static const BYTE PKCSSignerWithAuthAttr[] = {
6296 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6297 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6298 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6299 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6300 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6301 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6302 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6303
6304 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6305 {
6306     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6307     BOOL ret;
6308     LPBYTE buf = NULL;
6309     DWORD size = 0;
6310     CMSG_SIGNER_INFO info = { 0 };
6311     char oid_common_name[] = szOID_COMMON_NAME;
6312     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6313      (LPBYTE)encodedCommonName };
6314     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6315
6316     SetLastError(0xdeadbeef);
6317     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6318      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6319     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6320     {
6321         skip("no PKCS7_SIGNER_INFO encode support\n");
6322         return;
6323     }
6324     ok(!ret && (GetLastError() == E_INVALIDARG ||
6325      GetLastError() == OSS_LIMITED /* Win9x */),
6326      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6327     /* To be encoded, a signer must have an issuer at least, and the encoding
6328      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6329      * see decoding tests.)
6330      */
6331     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6332     info.Issuer.pbData = encodedCommonNameNoNull;
6333     SetLastError(0xdeadbeef);
6334     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6335      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6336     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6337         ok(!ret && GetLastError() == E_INVALIDARG,
6338          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6339     else
6340     {
6341         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6342          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6343         if (buf)
6344         {
6345             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6346             if (size == sizeof(minimalPKCSSigner))
6347                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6348             else
6349                 ok(0, "Unexpected value\n");
6350             LocalFree(buf);
6351         }
6352     }
6353     info.SerialNumber.cbData = sizeof(serialNum);
6354     info.SerialNumber.pbData = (BYTE *)serialNum;
6355     SetLastError(0xdeadbeef);
6356     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6357      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6358     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6359         ok(!ret && GetLastError() == E_INVALIDARG,
6360          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6361     else
6362     {
6363         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6364          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6365         if (buf)
6366         {
6367             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6368              size);
6369             if (size == sizeof(PKCSSignerWithSerial))
6370                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6371                  "Unexpected value\n");
6372             else
6373                 ok(0, "Unexpected value\n");
6374             LocalFree(buf);
6375         }
6376     }
6377     info.HashAlgorithm.pszObjId = oid1;
6378     SetLastError(0xdeadbeef);
6379     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6380      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6381     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6382         ok(!ret && GetLastError() == E_INVALIDARG,
6383          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6384     else
6385     {
6386         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6387          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6388         if (buf)
6389         {
6390             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6391              size);
6392             if (size == sizeof(PKCSSignerWithHashAlgo))
6393                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6394                  "Unexpected value\n");
6395             else
6396                 ok(0, "Unexpected value\n");
6397             LocalFree(buf);
6398         }
6399     }
6400     info.HashEncryptionAlgorithm.pszObjId = oid2;
6401     SetLastError(0xdeadbeef);
6402     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6403      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6404     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6405         ok(!ret && GetLastError() == E_INVALIDARG,
6406          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6407     else
6408     {
6409         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6410         if (buf)
6411         {
6412             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6413              "Unexpected size %d\n", size);
6414             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6415                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6416                  "Unexpected value\n");
6417             else
6418                 ok(0, "Unexpected value\n");
6419             LocalFree(buf);
6420         }
6421     }
6422     info.EncryptedHash.cbData = sizeof(hash);
6423     info.EncryptedHash.pbData = (BYTE *)hash;
6424     SetLastError(0xdeadbeef);
6425     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6426      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6427     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6428         ok(!ret && GetLastError() == E_INVALIDARG,
6429          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6430     else
6431     {
6432         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6433         if (buf)
6434         {
6435             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6436              size);
6437             if (size == sizeof(PKCSSignerWithHash))
6438                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6439                  "Unexpected value\n");
6440             else
6441                 ok(0, "Unexpected value\n");
6442             LocalFree(buf);
6443         }
6444     }
6445     info.AuthAttrs.cAttr = 1;
6446     info.AuthAttrs.rgAttr = &attr;
6447     SetLastError(0xdeadbeef);
6448     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6450     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6451         ok(!ret && GetLastError() == E_INVALIDARG,
6452          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6453     else
6454     {
6455         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6456         if (buf)
6457         {
6458             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6459              size);
6460             if (size == sizeof(PKCSSignerWithAuthAttr))
6461                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6462                  "Unexpected value\n");
6463             else
6464                 ok(0, "Unexpected value\n");
6465             LocalFree(buf);
6466         }
6467     }
6468 }
6469
6470 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6471 {
6472     BOOL ret;
6473     LPBYTE buf = NULL;
6474     DWORD size = 0;
6475     CMSG_SIGNER_INFO *info;
6476
6477     /* A PKCS signer can't be decoded without a serial number. */
6478     SetLastError(0xdeadbeef);
6479     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6480      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6481      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6482     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6483      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6484      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6485      GetLastError());
6486     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6487      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6488      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6489     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6490      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6491     if (buf)
6492     {
6493         info = (CMSG_SIGNER_INFO *)buf;
6494         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6495          info->dwVersion);
6496         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6497          "Unexpected size %d\n", info->Issuer.cbData);
6498         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6499          info->Issuer.cbData), "Unexpected value\n");
6500         ok(info->SerialNumber.cbData == sizeof(serialNum),
6501          "Unexpected size %d\n", info->SerialNumber.cbData);
6502         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6503          "Unexpected value\n");
6504         LocalFree(buf);
6505     }
6506     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6507      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6508      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6509     if (buf)
6510     {
6511         info = (CMSG_SIGNER_INFO *)buf;
6512         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6513          info->dwVersion);
6514         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6515          "Unexpected size %d\n", info->Issuer.cbData);
6516         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6517          info->Issuer.cbData), "Unexpected value\n");
6518         ok(info->SerialNumber.cbData == sizeof(serialNum),
6519          "Unexpected size %d\n", info->SerialNumber.cbData);
6520         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6521          "Unexpected value\n");
6522         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6523          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6524         LocalFree(buf);
6525     }
6526     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6527      PKCSSignerWithHashAndEncryptionAlgo,
6528      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6529      NULL, &buf, &size);
6530     if (buf)
6531     {
6532         info = (CMSG_SIGNER_INFO *)buf;
6533         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6534          info->dwVersion);
6535         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6536          "Unexpected size %d\n", info->Issuer.cbData);
6537         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6538          info->Issuer.cbData), "Unexpected value\n");
6539         ok(info->SerialNumber.cbData == sizeof(serialNum),
6540          "Unexpected size %d\n", info->SerialNumber.cbData);
6541         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6542          "Unexpected value\n");
6543         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6544          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6545         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6546          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6547         LocalFree(buf);
6548     }
6549     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6550      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6551      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6552     if (buf)
6553     {
6554         info = (CMSG_SIGNER_INFO *)buf;
6555         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6556          info->dwVersion);
6557         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6558          "Unexpected size %d\n", info->Issuer.cbData);
6559         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6560          info->Issuer.cbData), "Unexpected value\n");
6561         ok(info->SerialNumber.cbData == sizeof(serialNum),
6562          "Unexpected size %d\n", info->SerialNumber.cbData);
6563         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6564          "Unexpected value\n");
6565         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6566          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6567         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6568          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6569         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6570          info->EncryptedHash.cbData);
6571         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6572          "Unexpected value\n");
6573         LocalFree(buf);
6574     }
6575     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6576      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6577      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6578     if (buf)
6579     {
6580         info = (CMSG_SIGNER_INFO *)buf;
6581         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6582          info->AuthAttrs.cAttr);
6583         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6584          "Expected %s, got %s\n", szOID_COMMON_NAME,
6585          info->AuthAttrs.rgAttr[0].pszObjId);
6586         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6587          info->AuthAttrs.rgAttr[0].cValue);
6588         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6589          sizeof(encodedCommonName), "Unexpected size %d\n",
6590          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6591         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6592          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6593         LocalFree(buf);
6594     }
6595 }
6596
6597 static const BYTE CMSSignerWithKeyId[] = {
6598 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6599 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6600
6601 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6602 {
6603     BOOL ret;
6604     LPBYTE buf = NULL;
6605     DWORD size = 0;
6606     CMSG_CMS_SIGNER_INFO info = { 0 };
6607     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6608
6609     SetLastError(0xdeadbeef);
6610     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6611      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6612     ok(!ret, "Expected failure, got %d\n", ret);
6613     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6614     {
6615         skip("no CMS_SIGNER_INFO encode support\n");
6616         return;
6617     }
6618     ok(GetLastError() == E_INVALIDARG,
6619        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6620     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6621     SetLastError(0xdeadbeef);
6622     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6623      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6624     ok(!ret, "Expected failure, got %d\n", ret);
6625     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6626     {
6627         skip("no CMS_SIGNER_INFO encode support\n");
6628         return;
6629     }
6630     ok(GetLastError() == E_INVALIDARG,
6631        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6632     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6633      * be a key id or a issuer serial number with at least the issuer set, and
6634      * the encoding must include PKCS_7_ASN_ENCODING.
6635      * (That isn't enough to be decoded, see decoding tests.)
6636      */
6637     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6638      sizeof(encodedCommonNameNoNull);
6639     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6640     SetLastError(0xdeadbeef);
6641     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6642      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6643     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6644         ok(!ret && GetLastError() == E_INVALIDARG,
6645          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6646     else
6647     {
6648         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6649         if (buf)
6650         {
6651             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6652             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6653             LocalFree(buf);
6654         }
6655     }
6656     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6657     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6658     SetLastError(0xdeadbeef);
6659     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6660      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6661     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6662         ok(!ret && GetLastError() == E_INVALIDARG,
6663          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6664     else
6665     {
6666         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6667         if (buf)
6668         {
6669             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6670              size);
6671             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6672             LocalFree(buf);
6673         }
6674     }
6675     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6676     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6677     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6678     SetLastError(0xdeadbeef);
6679     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6680      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6681     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6682         ok(!ret && GetLastError() == E_INVALIDARG,
6683          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6684     else
6685     {
6686         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6687         if (buf)
6688         {
6689             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6690              size);
6691             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6692             LocalFree(buf);
6693         }
6694     }
6695     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6696      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6697      * (see RFC 3852, section 5.3.)
6698      */
6699     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6700     U(info.SignerId).HashId.cbData = sizeof(hash);
6701     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6702     SetLastError(0xdeadbeef);
6703     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6704      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6705     ok(!ret && GetLastError() == E_INVALIDARG,
6706      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6707     /* Now with a hash algo */
6708     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6709     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6710      sizeof(encodedCommonNameNoNull);
6711     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6712     info.HashAlgorithm.pszObjId = oid1;
6713     SetLastError(0xdeadbeef);
6714     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6715      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6716     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6717         ok(!ret && GetLastError() == E_INVALIDARG,
6718          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6719     else
6720     {
6721         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6722         if (buf)
6723         {
6724             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6725              size);
6726             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6727              "Unexpected value\n");
6728             LocalFree(buf);
6729         }
6730     }
6731     info.HashEncryptionAlgorithm.pszObjId = oid2;
6732     SetLastError(0xdeadbeef);
6733     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6734      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6735     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6736         ok(!ret && GetLastError() == E_INVALIDARG,
6737          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6738     else
6739     {
6740         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6741         if (buf)
6742         {
6743             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6744              "Unexpected size %d\n", size);
6745             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6746              "Unexpected value\n");
6747             LocalFree(buf);
6748         }
6749     }
6750     info.EncryptedHash.cbData = sizeof(hash);
6751     info.EncryptedHash.pbData = (BYTE *)hash;
6752     SetLastError(0xdeadbeef);
6753     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6754      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6755     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6756         ok(!ret && GetLastError() == E_INVALIDARG,
6757          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6758     else
6759     {
6760         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6761         if (buf)
6762         {
6763             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6764              size);
6765             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6766             LocalFree(buf);
6767         }
6768     }
6769 }
6770
6771 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6772 {
6773     BOOL ret;
6774     LPBYTE buf = NULL;
6775     DWORD size = 0;
6776     CMSG_CMS_SIGNER_INFO *info;
6777     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6778
6779     /* A CMS signer can't be decoded without a serial number. */
6780     SetLastError(0xdeadbeef);
6781     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6782      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6783      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6784     ok(!ret, "expected failure\n");
6785     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6786     {
6787         skip("no CMS_SIGNER_INFO decode support\n");
6788         return;
6789     }
6790     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6791      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6792     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6793      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6794      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6795     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6796     if (buf)
6797     {
6798         info = (CMSG_CMS_SIGNER_INFO *)buf;
6799         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6800          info->dwVersion);
6801         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6802          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6803          info->SignerId.dwIdChoice);
6804         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6805          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6806          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6807         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6808          encodedCommonNameNoNull,
6809          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6810          "Unexpected value\n");
6811         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6812          sizeof(serialNum), "Unexpected size %d\n",
6813          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6814         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6815          serialNum, sizeof(serialNum)), "Unexpected value\n");
6816         LocalFree(buf);
6817     }
6818     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6819      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6820      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6821     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6822     if (buf)
6823     {
6824         info = (CMSG_CMS_SIGNER_INFO *)buf;
6825         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6826          info->dwVersion);
6827         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6828          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6829          info->SignerId.dwIdChoice);
6830         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6831          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6832          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6833         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6834          encodedCommonNameNoNull,
6835          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6836          "Unexpected value\n");
6837         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6838          sizeof(serialNum), "Unexpected size %d\n",
6839          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6840         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6841          serialNum, sizeof(serialNum)), "Unexpected value\n");
6842         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6843          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6844         LocalFree(buf);
6845     }
6846     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6847      PKCSSignerWithHashAndEncryptionAlgo,
6848      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6849      NULL, &buf, &size);
6850     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6851     if (buf)
6852     {
6853         info = (CMSG_CMS_SIGNER_INFO *)buf;
6854         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6855          info->dwVersion);
6856         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6857          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6858          info->SignerId.dwIdChoice);
6859         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6860          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6861          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6862         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6863          encodedCommonNameNoNull,
6864          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6865          "Unexpected value\n");
6866         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6867          sizeof(serialNum), "Unexpected size %d\n",
6868          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6869         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6870          serialNum, sizeof(serialNum)), "Unexpected value\n");
6871         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6872          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6873         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6874          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6875         LocalFree(buf);
6876     }
6877     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6878      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6879      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6880     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6881     if (buf)
6882     {
6883         info = (CMSG_CMS_SIGNER_INFO *)buf;
6884         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6885          info->dwVersion);
6886         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6887          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6888          info->SignerId.dwIdChoice);
6889         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6890          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6891          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6892         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6893          encodedCommonNameNoNull,
6894          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6895          "Unexpected value\n");
6896         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6897          sizeof(serialNum), "Unexpected size %d\n",
6898          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6899         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6900          serialNum, sizeof(serialNum)), "Unexpected value\n");
6901         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6902          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6903         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6904          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6905         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6906          info->EncryptedHash.cbData);
6907         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6908          "Unexpected value\n");
6909         LocalFree(buf);
6910     }
6911     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6912      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6913      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6914     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6915     if (buf)
6916     {
6917         info = (CMSG_CMS_SIGNER_INFO *)buf;
6918         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6919          info->dwVersion);
6920         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6921          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6922          info->SignerId.dwIdChoice);
6923         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6924          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6925         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6926          "Unexpected value\n");
6927         LocalFree(buf);
6928     }
6929 }
6930
6931 static BYTE emptyDNSPermittedConstraints[] = {
6932 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6933 static BYTE emptyDNSExcludedConstraints[] = {
6934 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6935 static BYTE DNSExcludedConstraints[] = {
6936 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6937 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6938 static BYTE permittedAndExcludedConstraints[] = {
6939 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6940 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6941 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6942 static BYTE permittedAndExcludedWithMinConstraints[] = {
6943 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6944 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6945 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6946 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6947 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6948 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6949 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6950
6951 static void test_encodeNameConstraints(DWORD dwEncoding)
6952 {
6953     BOOL ret;
6954     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6955     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6956     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6957     LPBYTE buf;
6958     DWORD size;
6959
6960     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6961      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6962     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6963     {
6964         skip("no X509_NAME_CONSTRAINTS encode support\n");
6965         return;
6966     }
6967     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6968     if (ret)
6969     {
6970         ok(size == sizeof(emptySequence), "Unexpected size\n");
6971         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6972         LocalFree(buf);
6973     }
6974     constraints.cPermittedSubtree = 1;
6975     constraints.rgPermittedSubtree = &permitted;
6976     SetLastError(0xdeadbeef);
6977     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6978      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6979     ok(!ret && GetLastError() == E_INVALIDARG,
6980      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6981     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6982     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6984     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6985     if (ret)
6986     {
6987         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6988         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6989          "Unexpected value\n");
6990         LocalFree(buf);
6991     }
6992     constraints.cPermittedSubtree = 0;
6993     constraints.cExcludedSubtree = 1;
6994     constraints.rgExcludedSubtree = &excluded;
6995     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6996     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6997      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6998     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6999     if (ret)
7000     {
7001         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7002         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7003          "Unexpected value\n");
7004         LocalFree(buf);
7005     }
7006     U(excluded.Base).pwszURL = (LPWSTR)url;
7007     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7008      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7009     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7010     if (ret)
7011     {
7012         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7013         ok(!memcmp(buf, DNSExcludedConstraints, size),
7014          "Unexpected value\n");
7015         LocalFree(buf);
7016     }
7017     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7018     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7019     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7020     constraints.cPermittedSubtree = 1;
7021     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7022      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7023     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7024     if (ret)
7025     {
7026         ok(size == sizeof(permittedAndExcludedConstraints),
7027          "Unexpected size\n");
7028         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7029          "Unexpected value\n");
7030         LocalFree(buf);
7031     }
7032     permitted.dwMinimum = 5;
7033     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7034      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7035     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7036     if (ret)
7037     {
7038         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7039          "Unexpected size\n");
7040         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7041          "Unexpected value\n");
7042         LocalFree(buf);
7043     }
7044     permitted.fMaximum = TRUE;
7045     permitted.dwMaximum = 3;
7046     SetLastError(0xdeadbeef);
7047     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7048      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7049     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7050     if (ret)
7051     {
7052         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7053          "Unexpected size\n");
7054         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7055          "Unexpected value\n");
7056         LocalFree(buf);
7057     }
7058 }
7059
7060 struct EncodedNameConstraints
7061 {
7062     CRYPT_DATA_BLOB            encoded;
7063     CERT_NAME_CONSTRAINTS_INFO constraints;
7064 };
7065
7066 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7067  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7068 static CERT_GENERAL_SUBTREE DNSSubtree = {
7069  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7070 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7071  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7072 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7073  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7074 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7075  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7076
7077 struct EncodedNameConstraints encodedNameConstraints[] = {
7078  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7079  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7080    { 1, &emptyDNSSubtree, 0, NULL } },
7081  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7082    { 0, NULL, 1, &emptyDNSSubtree } },
7083  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7084    { 0, NULL, 1, &DNSSubtree } },
7085  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7086    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7087  { { sizeof(permittedAndExcludedWithMinConstraints),
7088      permittedAndExcludedWithMinConstraints },
7089    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7090  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7091      permittedAndExcludedWithMinMaxConstraints },
7092    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7093 };
7094
7095 static void test_decodeNameConstraints(DWORD dwEncoding)
7096 {
7097     BOOL ret;
7098     DWORD i;
7099     CERT_NAME_CONSTRAINTS_INFO *constraints;
7100
7101     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7102     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7103     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7104     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7105     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7106     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7107     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7108     for (i = 0;
7109      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7110      i++)
7111     {
7112         DWORD size;
7113
7114         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7115          encodedNameConstraints[i].encoded.pbData,
7116          encodedNameConstraints[i].encoded.cbData,
7117          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7118         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7119         {
7120             skip("no X509_NAME_CONSTRAINTS decode support\n");
7121             return;
7122         }
7123         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7124         if (ret)
7125         {
7126             DWORD j;
7127
7128             if (constraints->cPermittedSubtree !=
7129              encodedNameConstraints[i].constraints.cPermittedSubtree)
7130                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7131                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7132                  constraints->cPermittedSubtree);
7133             if (constraints->cPermittedSubtree ==
7134              encodedNameConstraints[i].constraints.cPermittedSubtree)
7135             {
7136                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7137                 {
7138                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7139                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7140                 }
7141             }
7142             if (constraints->cExcludedSubtree !=
7143              encodedNameConstraints[i].constraints.cExcludedSubtree)
7144                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7145                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7146                  constraints->cExcludedSubtree);
7147             if (constraints->cExcludedSubtree ==
7148              encodedNameConstraints[i].constraints.cExcludedSubtree)
7149             {
7150                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7151                 {
7152                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7153                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7154                 }
7155             }
7156             LocalFree(constraints);
7157         }
7158     }
7159 }
7160
7161 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7162  'n','o','t','i','c','e',0 };
7163 static const BYTE noticeWithDisplayText[] = {
7164  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7165  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7166  0x00,0x69,0x00,0x63,0x00,0x65
7167 };
7168 static char org[] = "Wine";
7169 static int noticeNumbers[] = { 2,3 };
7170 static BYTE noticeWithReference[] = {
7171  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7172  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7173  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7174  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7175 };
7176
7177 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7178 {
7179     BOOL ret;
7180     LPBYTE buf;
7181     DWORD size;
7182     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7183     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7184
7185     memset(&notice, 0, sizeof(notice));
7186     ret = pCryptEncodeObjectEx(dwEncoding,
7187      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7188      NULL, &buf, &size);
7189     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7190     {
7191         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7192         return;
7193     }
7194     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7195     if (ret)
7196     {
7197         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7198         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7199         LocalFree(buf);
7200     }
7201     notice.pszDisplayText = noticeText;
7202     ret = pCryptEncodeObjectEx(dwEncoding,
7203      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7204      NULL, &buf, &size);
7205     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7206     if (ret)
7207     {
7208         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7209         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7210         LocalFree(buf);
7211     }
7212     reference.pszOrganization = org;
7213     reference.cNoticeNumbers = 2;
7214     reference.rgNoticeNumbers = noticeNumbers;
7215     notice.pNoticeReference = &reference;
7216     ret = pCryptEncodeObjectEx(dwEncoding,
7217      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7218      NULL, &buf, &size);
7219     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7220     if (ret)
7221     {
7222         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7223         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7224         LocalFree(buf);
7225     }
7226 }
7227
7228 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7229 {
7230     BOOL ret;
7231     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7232     DWORD size;
7233
7234     ret = pCryptDecodeObjectEx(dwEncoding,
7235      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7236      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7237      &notice, &size);
7238     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7239     {
7240         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7241         return;
7242     }
7243     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7244     if (ret)
7245     {
7246         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7247         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7248         LocalFree(notice);
7249     }
7250     ret = pCryptDecodeObjectEx(dwEncoding,
7251      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7252      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7253      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7254     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7255     if (ret)
7256     {
7257         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7258          "unexpected display text\n");
7259         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7260         LocalFree(notice);
7261     }
7262     ret = pCryptDecodeObjectEx(dwEncoding,
7263      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7264      noticeWithReference, sizeof(noticeWithReference),
7265      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7266     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7267     if (ret)
7268     {
7269         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7270          "unexpected display text\n");
7271         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7272         if (notice->pNoticeReference)
7273         {
7274             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7275              "unexpected organization %s\n",
7276              notice->pNoticeReference->pszOrganization);
7277             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7278              "expected 2 notice numbers, got %d\n",
7279              notice->pNoticeReference->cNoticeNumbers);
7280             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7281              "unexpected notice number %d\n",
7282              notice->pNoticeReference->rgNoticeNumbers[0]);
7283             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7284              "unexpected notice number %d\n",
7285              notice->pNoticeReference->rgNoticeNumbers[1]);
7286         }
7287         LocalFree(notice);
7288     }
7289 }
7290
7291 static char oid_any_policy[] = "2.5.29.32.0";
7292 static const BYTE policiesWithAnyPolicy[] = {
7293  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7294 };
7295 static char oid1[] = "1.2.3";
7296 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7297 static const BYTE twoPolicies[] = {
7298  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7299  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7300  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7301  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7302  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7303  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7304 };
7305
7306 static void test_encodeCertPolicies(DWORD dwEncoding)
7307 {
7308     BOOL ret;
7309     CERT_POLICIES_INFO info;
7310     CERT_POLICY_INFO policy[2];
7311     CERT_POLICY_QUALIFIER_INFO qualifier;
7312     LPBYTE buf;
7313     DWORD size;
7314
7315     memset(&info, 0, sizeof(info));
7316     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7317      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7318     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7319     if (ret)
7320     {
7321         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7322         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7323         LocalFree(buf);
7324     }
7325     memset(policy, 0, sizeof(policy));
7326     info.cPolicyInfo = 1;
7327     info.rgPolicyInfo = policy;
7328     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7329      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7330     ok(!ret && (GetLastError() == E_INVALIDARG ||
7331      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7332      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7333     policy[0].pszPolicyIdentifier = oid_any_policy;
7334     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7335      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7336     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7337     if (ret)
7338     {
7339         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7340         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7341         LocalFree(buf);
7342     }
7343     policy[1].pszPolicyIdentifier = oid1;
7344     memset(&qualifier, 0, sizeof(qualifier));
7345     qualifier.pszPolicyQualifierId = oid_user_notice;
7346     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7347     qualifier.Qualifier.pbData = noticeWithReference;
7348     policy[1].cPolicyQualifier = 1;
7349     policy[1].rgPolicyQualifier = &qualifier;
7350     info.cPolicyInfo = 2;
7351     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7352      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7353     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7354     if (ret)
7355     {
7356         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7357         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7358         LocalFree(buf);
7359     }
7360 }
7361
7362 static void test_decodeCertPolicies(DWORD dwEncoding)
7363 {
7364     BOOL ret;
7365     CERT_POLICIES_INFO *info;
7366     DWORD size;
7367
7368     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7369      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7370      &info, &size);
7371     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7372     if (ret)
7373     {
7374         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7375          info->cPolicyInfo);
7376         LocalFree(info);
7377     }
7378     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7379      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7380      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7381     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7382     if (ret)
7383     {
7384         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7385          info->cPolicyInfo);
7386         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7387          "unexpected policy id %s\n",
7388          info->rgPolicyInfo[0].pszPolicyIdentifier);
7389         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7390          "unexpected policy qualifier count %d\n",
7391          info->rgPolicyInfo[0].cPolicyQualifier);
7392         LocalFree(info);
7393     }
7394     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7395      twoPolicies, sizeof(twoPolicies),
7396      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7397     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7398     if (ret)
7399     {
7400         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7401          info->cPolicyInfo);
7402         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7403          "unexpected policy id %s\n",
7404          info->rgPolicyInfo[0].pszPolicyIdentifier);
7405         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7406          "unexpected policy qualifier count %d\n",
7407          info->rgPolicyInfo[0].cPolicyQualifier);
7408         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7409          "unexpected policy id %s\n",
7410          info->rgPolicyInfo[1].pszPolicyIdentifier);
7411         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7412          "unexpected policy qualifier count %d\n",
7413          info->rgPolicyInfo[1].cPolicyQualifier);
7414         ok(!strcmp(
7415          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7416          oid_user_notice), "unexpected policy qualifier id %s\n",
7417          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7418         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7419          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7420          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7421         ok(!memcmp(
7422          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7423          noticeWithReference, sizeof(noticeWithReference)),
7424          "unexpected qualifier value\n");
7425         LocalFree(info);
7426     }
7427 }
7428
7429 /* Free *pInfo with HeapFree */
7430 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7431 {
7432     BOOL ret;
7433     DWORD size = 0;
7434     HCRYPTKEY key;
7435
7436     /* This crashes
7437     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7438      */
7439     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7440     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7441      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7442     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7443      &size);
7444     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7445      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7446     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7447      NULL, &size);
7448     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7449      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7450     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7451      0, NULL, NULL, &size);
7452     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7453      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7454     /* Test with no key */
7455     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7456      0, NULL, NULL, &size);
7457     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7458      GetLastError());
7459     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7460     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7461     if (ret)
7462     {
7463         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7464          NULL, 0, NULL, NULL, &size);
7465         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7466         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7467         if (*pInfo)
7468         {
7469             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7470              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7471             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7472              GetLastError());
7473             if (ret)
7474             {
7475                 /* By default (we passed NULL as the OID) the OID is
7476                  * szOID_RSA_RSA.
7477                  */
7478                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7479                  "Expected %s, got %s\n", szOID_RSA_RSA,
7480                  (*pInfo)->Algorithm.pszObjId);
7481             }
7482         }
7483     }
7484     CryptDestroyKey(key);
7485 }
7486
7487 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7488  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7489  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7490  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7491  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7492  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7493  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7494  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7495  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7496  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7497  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7498  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7499  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7500  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7501  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7502  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7503  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7504  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7505  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7506  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7507  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7508  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7509  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7510  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7511  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7512
7513 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7514 {
7515     BOOL ret;
7516     HCRYPTKEY key;
7517     PCCERT_CONTEXT context;
7518     DWORD dwSize;
7519     ALG_ID ai;
7520
7521     /* These crash
7522     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7523     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7524     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7525     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7526      NULL);
7527      */
7528     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7529     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7530      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7531     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7532     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7533      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7534     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7535      &key);
7536     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7537      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7538
7539     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7540     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7541      &key);
7542     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7543
7544     dwSize = sizeof(ai);
7545     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7546     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7547     if(ret)
7548     {
7549       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7550       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7551     }
7552
7553     CryptDestroyKey(key);
7554
7555     /* Repeat with forced algorithm */
7556     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7557      &key);
7558     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7559
7560     dwSize = sizeof(ai);
7561     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7562     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7563     if(ret)
7564     {
7565       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7566       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7567     }
7568
7569     CryptDestroyKey(key);
7570
7571     /* Test importing a public key from a certificate context */
7572     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7573      sizeof(expiredCert));
7574     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7575      GetLastError());
7576     if (context)
7577     {
7578         ok(!strcmp(szOID_RSA_RSA,
7579          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7580          "Expected %s, got %s\n", szOID_RSA_RSA,
7581          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7582         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7583          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7584         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7585         CryptDestroyKey(key);
7586         CertFreeCertificateContext(context);
7587     }
7588 }
7589
7590 static const char cspName[] = "WineCryptTemp";
7591
7592 static void testPortPublicKeyInfo(void)
7593 {
7594     HCRYPTPROV csp;
7595     BOOL ret;
7596     PCERT_PUBLIC_KEY_INFO info = NULL;
7597
7598     /* Just in case a previous run failed, delete this thing */
7599     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7600      CRYPT_DELETEKEYSET);
7601     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7602      CRYPT_NEWKEYSET);
7603
7604     testExportPublicKey(csp, &info);
7605     testImportPublicKey(csp, info);
7606
7607     HeapFree(GetProcessHeap(), 0, info);
7608     CryptReleaseContext(csp, 0);
7609     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7610      CRYPT_DELETEKEYSET);
7611 }
7612
7613 START_TEST(encode)
7614 {
7615     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7616      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7617     HMODULE hCrypt32;
7618     DWORD i;
7619
7620     hCrypt32 = GetModuleHandleA("crypt32.dll");
7621     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7622     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7623     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7624     {
7625         win_skip("CryptDecodeObjectEx() is not available\n");
7626         return;
7627     }
7628
7629     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7630     {
7631         test_encodeInt(encodings[i]);
7632         test_decodeInt(encodings[i]);
7633         test_encodeEnumerated(encodings[i]);
7634         test_decodeEnumerated(encodings[i]);
7635         test_encodeFiletime(encodings[i]);
7636         test_decodeFiletime(encodings[i]);
7637         test_encodeName(encodings[i]);
7638         test_decodeName(encodings[i]);
7639         test_encodeUnicodeName(encodings[i]);
7640         test_decodeUnicodeName(encodings[i]);
7641         test_encodeNameValue(encodings[i]);
7642         test_decodeNameValue(encodings[i]);
7643         test_encodeUnicodeNameValue(encodings[i]);
7644         test_decodeUnicodeNameValue(encodings[i]);
7645         test_encodeAltName(encodings[i]);
7646         test_decodeAltName(encodings[i]);
7647         test_encodeOctets(encodings[i]);
7648         test_decodeOctets(encodings[i]);
7649         test_encodeBits(encodings[i]);
7650         test_decodeBits(encodings[i]);
7651         test_encodeBasicConstraints(encodings[i]);
7652         test_decodeBasicConstraints(encodings[i]);
7653         test_encodeRsaPublicKey(encodings[i]);
7654         test_decodeRsaPublicKey(encodings[i]);
7655         test_encodeSequenceOfAny(encodings[i]);
7656         test_decodeSequenceOfAny(encodings[i]);
7657         test_encodeExtensions(encodings[i]);
7658         test_decodeExtensions(encodings[i]);
7659         test_encodePublicKeyInfo(encodings[i]);
7660         test_decodePublicKeyInfo(encodings[i]);
7661         test_encodeCertToBeSigned(encodings[i]);
7662         test_decodeCertToBeSigned(encodings[i]);
7663         test_encodeCert(encodings[i]);
7664         test_decodeCert(encodings[i]);
7665         test_encodeCRLDistPoints(encodings[i]);
7666         test_decodeCRLDistPoints(encodings[i]);
7667         test_encodeCRLIssuingDistPoint(encodings[i]);
7668         test_decodeCRLIssuingDistPoint(encodings[i]);
7669         test_encodeCRLToBeSigned(encodings[i]);
7670         test_decodeCRLToBeSigned(encodings[i]);
7671         test_encodeEnhancedKeyUsage(encodings[i]);
7672         test_decodeEnhancedKeyUsage(encodings[i]);
7673         test_encodeAuthorityKeyId(encodings[i]);
7674         test_decodeAuthorityKeyId(encodings[i]);
7675         test_encodeAuthorityKeyId2(encodings[i]);
7676         test_decodeAuthorityKeyId2(encodings[i]);
7677         test_encodeAuthorityInfoAccess(encodings[i]);
7678         test_decodeAuthorityInfoAccess(encodings[i]);
7679         test_encodeCTL(encodings[i]);
7680         test_decodeCTL(encodings[i]);
7681         test_encodePKCSContentInfo(encodings[i]);
7682         test_decodePKCSContentInfo(encodings[i]);
7683         test_encodePKCSAttribute(encodings[i]);
7684         test_decodePKCSAttribute(encodings[i]);
7685         test_encodePKCSAttributes(encodings[i]);
7686         test_decodePKCSAttributes(encodings[i]);
7687         test_encodePKCSSMimeCapabilities(encodings[i]);
7688         test_decodePKCSSMimeCapabilities(encodings[i]);
7689         test_encodePKCSSignerInfo(encodings[i]);
7690         test_decodePKCSSignerInfo(encodings[i]);
7691         test_encodeCMSSignerInfo(encodings[i]);
7692         test_decodeCMSSignerInfo(encodings[i]);
7693         test_encodeNameConstraints(encodings[i]);
7694         test_decodeNameConstraints(encodings[i]);
7695         test_encodePolicyQualifierUserNotice(encodings[i]);
7696         test_decodePolicyQualifierUserNotice(encodings[i]);
7697         test_encodeCertPolicies(encodings[i]);
7698         test_decodeCertPolicies(encodings[i]);
7699     }
7700     testPortPublicKeyInfo();
7701 }