oleaut32: Do no check for dispatchable flag on dual interfaces.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (buf)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (buf)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (buf)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (buf)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (buf)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (buf)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              &val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (buf)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666            broken(ret), /* Win9x and NT4 for bin38 */
667          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668          GetLastError());
669     }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690  0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692  0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694  0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698  0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[]            = "2.5.4.6",
706             oid_minnesota[]     = "2.5.4.8",
707             oid_minneapolis[]   = "2.5.4.7",
708             oid_codeweavers[]   = "2.5.4.10",
709             oid_wine[]          = "2.5.4.11",
710             oid_localhostAttr[] = "2.5.4.3",
711             oid_aric[]          = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713                                     { RDNA(minnesota) },
714                                     { RDNA(minneapolis) },
715                                     { RDNA(codeweavers) },
716                                     { RDNA(wine) },
717                                     { RDNA(localhostAttr) },
718                                     { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720                                            { RDNA(localhostAttr) },
721                                            { RDNA(minnesota) },
722                                            { RDNA(minneapolis) },
723                                            { RDNA(codeweavers) },
724                                            { RDNA(wine) },
725                                            { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745     CERT_RDN_ATTR attrs[2];
746     CERT_RDN rdn;
747     CERT_NAME_INFO info;
748     static CHAR oid_common_name[] = szOID_COMMON_NAME,
749                 oid_sur_name[]    = szOID_SUR_NAME;
750     BYTE *buf = NULL;
751     DWORD size = 0;
752     BOOL ret;
753
754     if (0)
755     {
756         /* Test with NULL pvStructInfo (crashes on win9x) */
757         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761     }
762     /* Test with empty CERT_NAME_INFO */
763     info.cRDN = 0;
764     info.rgRDN = NULL;
765     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (buf)
769     {
770         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771          "Got unexpected encoding for empty name\n");
772         LocalFree(buf);
773     }
774     if (0)
775     {
776         /* Test with bogus CERT_RDN (crashes on win9x) */
777         info.cRDN = 1;
778         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782     }
783     /* Test with empty CERT_RDN */
784     rdn.cRDNAttr = 0;
785     rdn.rgRDNAttr = NULL;
786     info.cRDN = 1;
787     info.rgRDN = &rdn;
788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791     if (buf)
792     {
793         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794          "Got unexpected encoding for empty RDN array\n");
795         LocalFree(buf);
796     }
797     if (0)
798     {
799         /* Test with bogus attr array (crashes on win9x) */
800         rdn.cRDNAttr = 1;
801         rdn.rgRDNAttr = NULL;
802         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806     }
807     /* oddly, a bogus OID is accepted by Windows XP; not testing.
808     attrs[0].pszObjId = "bogus";
809     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810     attrs[0].Value.cbData = sizeof(commonName);
811     attrs[0].Value.pbData = commonName;
812     rdn.cRDNAttr = 1;
813     rdn.rgRDNAttr = attrs;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816     ok(!ret, "Expected failure, got success\n");
817      */
818     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
819      * the encoded attributes to be swapped.
820      */
821     attrs[0].pszObjId = oid_common_name;
822     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823     attrs[0].Value.cbData = sizeof(commonName);
824     attrs[0].Value.pbData = (BYTE *)commonName;
825     attrs[1].pszObjId = oid_sur_name;
826     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827     attrs[1].Value.cbData = sizeof(surName);
828     attrs[1].Value.pbData = (BYTE *)surName;
829     rdn.cRDNAttr = 2;
830     rdn.rgRDNAttr = attrs;
831     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834     if (buf)
835     {
836         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837          "Got unexpected encoding for two RDN array\n");
838         LocalFree(buf);
839     }
840     /* A name can be "encoded" with previously encoded RDN attrs. */
841     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843     attrs[0].Value.cbData = sizeof(twoRDNs);
844     rdn.cRDNAttr = 1;
845     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848     if (buf)
849     {
850         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851         ok(!memcmp(buf, encodedTwoRDNs, size),
852          "Unexpected value for re-endoded two RDN array\n");
853         LocalFree(buf);
854     }
855     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856     rdn.cRDNAttr = 1;
857     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860     ok(!ret && GetLastError() == E_INVALIDARG,
861      "Expected E_INVALIDARG, got %08x\n", GetLastError());
862     /* Test a more complex name */
863     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864     rdn.rgRDNAttr = rdnAttrs;
865     info.cRDN = 1;
866     info.rgRDN = &rdn;
867     buf = NULL;
868     size = 0;
869     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872     if (ret)
873     {
874         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876         LocalFree(buf);
877     }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886  0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891  0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895     CERT_RDN_ATTR attrs[2];
896     CERT_RDN rdn;
897     CERT_NAME_INFO info;
898     static CHAR oid_common_name[] = szOID_COMMON_NAME,
899                 oid_sur_name[]    = szOID_SUR_NAME;
900     BYTE *buf = NULL;
901     DWORD size = 0;
902     BOOL ret;
903
904     if (0)
905     {
906         /* Test with NULL pvStructInfo (crashes on win9x) */
907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911     }
912     /* Test with empty CERT_NAME_INFO */
913     info.cRDN = 0;
914     info.rgRDN = NULL;
915     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918     if (buf)
919     {
920         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921          "Got unexpected encoding for empty name\n");
922         LocalFree(buf);
923     }
924     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925      * encoding (the NULL).
926      */
927     attrs[0].pszObjId = oid_common_name;
928     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929     attrs[0].Value.cbData = sizeof(commonNameW);
930     attrs[0].Value.pbData = (BYTE *)commonNameW;
931     rdn.cRDNAttr = 1;
932     rdn.rgRDNAttr = attrs;
933     info.cRDN = 1;
934     info.rgRDN = &rdn;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939     ok(size == 9, "Unexpected error index %08x\n", size);
940     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
941      * forces the order of the encoded attributes to be swapped.
942      */
943     attrs[0].pszObjId = oid_common_name;
944     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945     attrs[0].Value.cbData = 0;
946     attrs[0].Value.pbData = (BYTE *)commonNameW;
947     attrs[1].pszObjId = oid_sur_name;
948     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949     attrs[1].Value.cbData = 0;
950     attrs[1].Value.pbData = (BYTE *)surNameW;
951     rdn.cRDNAttr = 2;
952     rdn.rgRDNAttr = attrs;
953     info.cRDN = 1;
954     info.rgRDN = &rdn;
955     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958     if (buf)
959     {
960         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961          "Got unexpected encoding for two RDN array\n");
962         LocalFree(buf);
963     }
964     /* A name can be "encoded" with previously encoded RDN attrs. */
965     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967     attrs[0].Value.cbData = sizeof(twoRDNs);
968     rdn.cRDNAttr = 1;
969     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972     if (buf)
973     {
974         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975         ok(!memcmp(buf, encodedTwoRDNs, size),
976          "Unexpected value for re-endoded two RDN array\n");
977         LocalFree(buf);
978     }
979     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980     rdn.cRDNAttr = 1;
981     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985     if (buf)
986     {
987         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989         LocalFree(buf);
990     }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994  const CERT_NAME_VALUE *got)
995 {
996     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997         got->dwValueType == CERT_RDN_ENCODED_BLOB)
998     {
999         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000         return;
1001     }
1002
1003     ok(got->dwValueType == expected->dwValueType,
1004      "Expected string type %d, got %d\n", expected->dwValueType,
1005      got->dwValueType);
1006     ok(got->Value.cbData == expected->Value.cbData,
1007      "String type %d: unexpected data size, got %d, expected %d\n",
1008      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009     if (got->Value.cbData && got->Value.pbData)
1010         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011          min(got->Value.cbData, expected->Value.cbData)),
1012          "String type %d: unexpected value\n", expected->dwValueType);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016  const CERT_RDN_ATTR *got)
1017 {
1018     if (expected->pszObjId && strlen(expected->pszObjId))
1019     {
1020         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021          expected->pszObjId);
1022         if (got->pszObjId)
1023         {
1024             ok(!strcmp(got->pszObjId, expected->pszObjId),
1025              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026              expected->pszObjId);
1027         }
1028     }
1029     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030      (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035     ok(got->cRDNAttr == expected->cRDNAttr,
1036      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037     if (got->cRDNAttr)
1038     {
1039         DWORD i;
1040
1041         for (i = 0; i < got->cRDNAttr; i++)
1042             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043     }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047  const CERT_NAME_INFO *got)
1048 {
1049     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050      expected->cRDN, got->cRDN);
1051     if (got->cRDN)
1052     {
1053         DWORD i;
1054
1055         for (i = 0; i < got->cRDN; i++)
1056             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057     }
1058 }
1059
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068     BYTE *buf = NULL;
1069     DWORD bufSize = 0;
1070     BOOL ret;
1071     CERT_RDN rdn;
1072     CERT_NAME_INFO info = { 1, &rdn };
1073
1074     /* test empty name */
1075     bufSize = 0;
1076     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077      emptySequence[1] + 2,
1078      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079      &buf, &bufSize);
1080     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1082      * decoder works the same way, so only test the count.
1083      */
1084     if (buf)
1085     {
1086         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088          "Expected 0 RDNs in empty info, got %d\n",
1089          ((CERT_NAME_INFO *)buf)->cRDN);
1090         LocalFree(buf);
1091     }
1092     /* test empty name with indefinite-length encoding */
1093     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095      &buf, &bufSize);
1096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097     if (ret)
1098     {
1099         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101          "Expected 0 RDNs in empty info, got %d\n",
1102          ((CERT_NAME_INFO *)buf)->cRDN);
1103         LocalFree(buf);
1104     }
1105     /* test empty RDN */
1106     bufSize = 0;
1107     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108      emptyRDNs[1] + 2,
1109      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110      &buf, &bufSize);
1111     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112     if (buf)
1113     {
1114         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
1116         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118          "Got unexpected value for empty RDN\n");
1119         LocalFree(buf);
1120     }
1121     /* test two RDN attrs */
1122     bufSize = 0;
1123     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124      twoRDNs[1] + 2,
1125      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126      &buf, &bufSize);
1127     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128     if (buf)
1129     {
1130         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1131                     oid_common_name[] = szOID_COMMON_NAME;
1132
1133         CERT_RDN_ATTR attrs[] = {
1134          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135           (BYTE *)surName } },
1136          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137           (BYTE *)commonName } },
1138         };
1139
1140         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141         rdn.rgRDNAttr = attrs;
1142         compareNames(&info, (CERT_NAME_INFO *)buf);
1143         LocalFree(buf);
1144     }
1145     /* test that two RDN attrs with extra bytes succeeds */
1146     bufSize = 0;
1147     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150     /* And, a slightly more complicated name */
1151     buf = NULL;
1152     bufSize = 0;
1153     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156     if (ret)
1157     {
1158         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159         rdn.rgRDNAttr = decodedRdnAttrs;
1160         compareNames(&info, (CERT_NAME_INFO *)buf);
1161         LocalFree(buf);
1162     }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167     BYTE *buf = NULL;
1168     DWORD bufSize = 0;
1169     BOOL ret;
1170     CERT_RDN rdn;
1171     CERT_NAME_INFO info = { 1, &rdn };
1172
1173     /* test empty name */
1174     bufSize = 0;
1175     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176      emptySequence[1] + 2,
1177      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178      &buf, &bufSize);
1179     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180     if (buf)
1181     {
1182         ok(bufSize == sizeof(CERT_NAME_INFO),
1183          "Got wrong bufSize %d\n", bufSize);
1184         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185          "Expected 0 RDNs in empty info, got %d\n",
1186          ((CERT_NAME_INFO *)buf)->cRDN);
1187         LocalFree(buf);
1188     }
1189     /* test empty RDN */
1190     bufSize = 0;
1191     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192      emptyRDNs[1] + 2,
1193      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194      &buf, &bufSize);
1195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196     if (buf)
1197     {
1198         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
1200         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202          "Got unexpected value for empty RDN\n");
1203         LocalFree(buf);
1204     }
1205     /* test two RDN attrs */
1206     bufSize = 0;
1207     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208      sizeof(twoRDNsNoNull),
1209      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210      &buf, &bufSize);
1211     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212     if (buf)
1213     {
1214         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1215                     oid_common_name[] = szOID_COMMON_NAME;
1216
1217         CERT_RDN_ATTR attrs[] = {
1218          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1222         };
1223
1224         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225         rdn.rgRDNAttr = attrs;
1226         compareNames(&info, (CERT_NAME_INFO *)buf);
1227         LocalFree(buf);
1228     }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233     CERT_NAME_VALUE value;
1234     const BYTE *encoded;
1235     DWORD encodedSize;
1236 };
1237
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1267 static char embedded_null[] = "foo\0com";
1268 static BYTE ia5EmbeddedNull[] = {
1269  0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1270
1271 static struct EncodedNameValue nameValues[] = {
1272  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273      octetCommonNameValue, sizeof(octetCommonNameValue) },
1274  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      numericCommonNameValue, sizeof(numericCommonNameValue) },
1276  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      printableCommonNameValue, sizeof(printableCommonNameValue) },
1278  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      t61CommonNameValue, sizeof(t61CommonNameValue) },
1280  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1282  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1284  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1286  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1288  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289      generalCommonNameValue, sizeof(generalCommonNameValue) },
1290  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1291      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1292  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1294  /* The following tests succeed under Windows, but really should fail,
1295   * they contain characters that are illegal for the encoding.  I'm
1296   * including them to justify my lazy encoding.
1297   */
1298  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1299      sizeof(bin42) },
1300  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1301      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1302  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1303      bin44, sizeof(bin44) },
1304 };
1305 /* This is kept separate, because the decoding doesn't return to the original
1306  * value.
1307  */
1308 static struct EncodedNameValue embeddedNullNameValue = {
1309  { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1310    ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1311
1312 static void test_encodeNameValue(DWORD dwEncoding)
1313 {
1314     BYTE *buf = NULL;
1315     DWORD size = 0, i;
1316     BOOL ret;
1317     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1318
1319     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1320     value.Value.pbData = printableCommonNameValue;
1321     value.Value.cbData = sizeof(printableCommonNameValue);
1322     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1323      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1324     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1325     if (buf)
1326     {
1327         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1328          size);
1329         ok(!memcmp(buf, printableCommonNameValue, size),
1330          "Unexpected encoding\n");
1331         LocalFree(buf);
1332     }
1333     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1334     {
1335         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1336          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1337         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1338          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1339          nameValues[i].value.dwValueType, GetLastError());
1340         if (ret)
1341         {
1342             ok(size == nameValues[i].encodedSize,
1343              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1344             ok(!memcmp(buf, nameValues[i].encoded, size),
1345              "Got unexpected encoding\n");
1346             LocalFree(buf);
1347         }
1348     }
1349     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1350      &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1351     ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1352      "Type %d: CryptEncodeObjectEx failed: %08x\n",
1353      embeddedNullNameValue.value.dwValueType, GetLastError());
1354     if (ret)
1355     {
1356         ok(size == embeddedNullNameValue.encodedSize,
1357          "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1358         ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1359          "Got unexpected encoding\n");
1360         LocalFree(buf);
1361     }
1362 }
1363
1364 static void test_decodeNameValue(DWORD dwEncoding)
1365 {
1366     int i;
1367     BYTE *buf = NULL;
1368     DWORD bufSize = 0;
1369     BOOL ret;
1370
1371     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1372     {
1373         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1374          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1375          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1376          &buf, &bufSize);
1377         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1378          nameValues[i].value.dwValueType, GetLastError());
1379         if (ret)
1380         {
1381             compareNameValues(&nameValues[i].value,
1382              (const CERT_NAME_VALUE *)buf);
1383             LocalFree(buf);
1384         }
1385     }
1386     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1387      embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1388      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1389      &buf, &bufSize);
1390     ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1391      embeddedNullNameValue.value.dwValueType, GetLastError());
1392     if (ret)
1393     {
1394         CERT_NAME_VALUE value = { CERT_RDN_ENCODED_BLOB,
1395          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1396
1397         todo_wine
1398         compareNameValues(&value, (const CERT_NAME_VALUE *)buf);
1399         LocalFree(buf);
1400     }
1401 }
1402
1403 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1404 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1405 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1406  'h','q','.','o','r','g',0 };
1407 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1408  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1409  0x6f, 0x72, 0x67 };
1410 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1411  0x575b, 0 };
1412 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1413 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1414  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1415 static const BYTE localhost[] = { 127, 0, 0, 1 };
1416 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1417  0x01 };
1418 static const unsigned char encodedCommonName[] = {
1419     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1420 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1421 static const BYTE encodedDirectoryName[] = {
1422 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1423 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1424
1425 static void test_encodeAltName(DWORD dwEncoding)
1426 {
1427     CERT_ALT_NAME_INFO info = { 0 };
1428     CERT_ALT_NAME_ENTRY entry = { 0 };
1429     BYTE *buf = NULL;
1430     DWORD size = 0;
1431     BOOL ret;
1432     char oid[] = "1.2.3";
1433
1434     /* Test with empty info */
1435     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437     if (buf)
1438     {
1439         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1440         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1441         LocalFree(buf);
1442     }
1443     /* Test with an empty entry */
1444     info.cAltEntry = 1;
1445     info.rgAltEntry = &entry;
1446     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1447      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1448     ok(!ret && GetLastError() == E_INVALIDARG,
1449      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1450     /* Test with an empty pointer */
1451     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1452     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1454     if (buf)
1455     {
1456         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1457         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1458         LocalFree(buf);
1459     }
1460     /* Test with a real URL */
1461     U(entry).pwszURL = (LPWSTR)url;
1462     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1464     if (buf)
1465     {
1466         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1467         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1468         LocalFree(buf);
1469     }
1470     /* Now with the URL containing an invalid IA5 char */
1471     U(entry).pwszURL = (LPWSTR)nihongoURL;
1472     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1473      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1474     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1475      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1476     /* The first invalid character is at index 7 */
1477     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1478      "Expected invalid char at index 7, got %d\n",
1479      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1480     /* Now with the URL missing a scheme */
1481     U(entry).pwszURL = (LPWSTR)dnsName;
1482     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1483      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1484     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1485     if (buf)
1486     {
1487         /* This succeeds, but it shouldn't, so don't worry about conforming */
1488         LocalFree(buf);
1489     }
1490     /* Now with a DNS name */
1491     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1492     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1493      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1494     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1495     if (buf)
1496     {
1497         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1498         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1499         LocalFree(buf);
1500     }
1501     /* Test with an IP address */
1502     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1503     U(entry).IPAddress.cbData = sizeof(localhost);
1504     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1505     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1506      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1507     if (buf)
1508     {
1509         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1510         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1511         LocalFree(buf);
1512     }
1513     /* Test with OID */
1514     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1515     U(entry).pszRegisteredID = oid;
1516     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1517      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1518     if (buf)
1519     {
1520         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1521         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1522         LocalFree(buf);
1523     }
1524     /* Test with directory name */
1525     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1526     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1527     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1528     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1529      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1530     if (buf)
1531     {
1532         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1533         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1534         LocalFree(buf);
1535     }
1536 }
1537
1538 static void test_decodeAltName(DWORD dwEncoding)
1539 {
1540     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1541      0x00, 0x00, 0x01 };
1542     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1543      0x01 };
1544     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1545      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1546     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1547      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1548     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1549      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1550     BOOL ret;
1551     BYTE *buf = NULL;
1552     DWORD bufSize = 0;
1553     CERT_ALT_NAME_INFO *info;
1554
1555     /* Test some bogus ones first */
1556     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1557      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1558      NULL, &buf, &bufSize);
1559     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1560      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1561      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1562      GetLastError());
1563     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1564      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1565      &bufSize);
1566     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1567      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1568      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1569      GetLastError());
1570     /* Now expected cases */
1571     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1572      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1573     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1574     if (buf)
1575     {
1576         info = (CERT_ALT_NAME_INFO *)buf;
1577
1578         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1579          info->cAltEntry);
1580         LocalFree(buf);
1581     }
1582     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1583      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1584     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1585     if (buf)
1586     {
1587         info = (CERT_ALT_NAME_INFO *)buf;
1588
1589         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1590          info->cAltEntry);
1591         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1592          "Expected CERT_ALT_NAME_URL, got %d\n",
1593          info->rgAltEntry[0].dwAltNameChoice);
1594         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1595          "Expected empty URL\n");
1596         LocalFree(buf);
1597     }
1598     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1599      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1600     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1601     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1602      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1603     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1604     if (buf)
1605     {
1606         info = (CERT_ALT_NAME_INFO *)buf;
1607
1608         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1609          info->cAltEntry);
1610         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1611          "Expected CERT_ALT_NAME_URL, got %d\n",
1612          info->rgAltEntry[0].dwAltNameChoice);
1613         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1614         LocalFree(buf);
1615     }
1616     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1617      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1618     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1619     if (buf)
1620     {
1621         info = (CERT_ALT_NAME_INFO *)buf;
1622
1623         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1624          info->cAltEntry);
1625         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1626          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1627          info->rgAltEntry[0].dwAltNameChoice);
1628         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1629          "Unexpected DNS name\n");
1630         LocalFree(buf);
1631     }
1632     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1633      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1634     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1635     if (buf)
1636     {
1637         info = (CERT_ALT_NAME_INFO *)buf;
1638
1639         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1640          info->cAltEntry);
1641         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1642          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1643          info->rgAltEntry[0].dwAltNameChoice);
1644         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1645          "Unexpected IP address length %d\n",
1646           U(info->rgAltEntry[0]).IPAddress.cbData);
1647         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1648          sizeof(localhost)), "Unexpected IP address value\n");
1649         LocalFree(buf);
1650     }
1651     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1652      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1653     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1654     if (buf)
1655     {
1656         info = (CERT_ALT_NAME_INFO *)buf;
1657
1658         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1659          info->cAltEntry);
1660         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1661          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1662          info->rgAltEntry[0].dwAltNameChoice);
1663         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1664            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1665         LocalFree(buf);
1666     }
1667     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1668      encodedDirectoryName, sizeof(encodedDirectoryName),
1669      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1670     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1671     if (buf)
1672     {
1673         info = (CERT_ALT_NAME_INFO *)buf;
1674
1675         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1676          info->cAltEntry);
1677         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1678          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1679          info->rgAltEntry[0].dwAltNameChoice);
1680         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1681          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1682           U(info->rgAltEntry[0]).DirectoryName.cbData);
1683         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1684          encodedCommonName, sizeof(encodedCommonName)),
1685          "Unexpected directory name value\n");
1686         LocalFree(buf);
1687     }
1688     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1689      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1690      NULL, &buf, &bufSize);
1691     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1692      * particular failure, just that it doesn't decode.
1693      */
1694     ok(!ret, "expected failure\n");
1695     /* An embedded bell character is allowed, however. */
1696     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1697      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1698      NULL, &buf, &bufSize);
1699     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1700     if (ret)
1701     {
1702         info = (CERT_ALT_NAME_INFO *)buf;
1703
1704         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1705          info->cAltEntry);
1706         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1707          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1708          info->rgAltEntry[0].dwAltNameChoice);
1709         LocalFree(buf);
1710     }
1711     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1712      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1713      NULL, &buf, &bufSize);
1714     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1715      * about the particular failure, just that it doesn't decode.
1716      */
1717     ok(!ret, "expected failure\n");
1718 }
1719
1720 struct UnicodeExpectedError
1721 {
1722     DWORD   valueType;
1723     LPCWSTR str;
1724     DWORD   errorIndex;
1725     DWORD   error;
1726 };
1727
1728 static const WCHAR oneW[] = { '1',0 };
1729 static const WCHAR aW[] = { 'a',0 };
1730 static const WCHAR quoteW[] = { '"', 0 };
1731
1732 static struct UnicodeExpectedError unicodeErrors[] = {
1733  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1734  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1735  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1736  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1737  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1738  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1739 };
1740
1741 struct UnicodeExpectedResult
1742 {
1743     DWORD           valueType;
1744     LPCWSTR         str;
1745     CRYPT_DATA_BLOB encoded;
1746 };
1747
1748 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1749 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1750 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1751 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1752 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1753 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1754 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1755 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1756 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1757 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1758 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1759 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1760  0x5b };
1761 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1762  0x6f,0x5b };
1763 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1764  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1765 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1766  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1767
1768 static struct UnicodeExpectedResult unicodeResults[] = {
1769  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1770  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1771  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1772  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1773  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1774  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1775  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1776  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1777  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1778  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1779  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1780  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1781  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1782 };
1783
1784 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1785  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1786  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1787 };
1788
1789 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1790 {
1791     BYTE *buf = NULL;
1792     DWORD size = 0, i;
1793     BOOL ret;
1794     CERT_NAME_VALUE value;
1795
1796     if (0)
1797     {
1798         /* Crashes on win9x */
1799         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1800          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1801         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1802          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1803     }
1804     /* Have to have a string of some sort */
1805     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1806     value.Value.pbData = NULL;
1807     value.Value.cbData = 0;
1808     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1809      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1810     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1811      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1812     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1813     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1814      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1815     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1816      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1817     value.dwValueType = CERT_RDN_ANY_TYPE;
1818     value.Value.pbData = (LPBYTE)oneW;
1819     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1820      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1821     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1822      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1823     value.Value.cbData = sizeof(oneW);
1824     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1825      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1826     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1827      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1828     /* An encoded string with specified length isn't good enough either */
1829     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1830     value.Value.pbData = oneUniversal;
1831     value.Value.cbData = sizeof(oneUniversal);
1832     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1833      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1834     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1835      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1836     /* More failure checking */
1837     value.Value.cbData = 0;
1838     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1839     {
1840         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1841         value.dwValueType = unicodeErrors[i].valueType;
1842         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1843          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1844         ok(!ret && GetLastError() == unicodeErrors[i].error,
1845          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1846          unicodeErrors[i].error, GetLastError());
1847         ok(size == unicodeErrors[i].errorIndex,
1848          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1849          size);
1850     }
1851     /* cbData can be zero if the string is NULL-terminated */
1852     value.Value.cbData = 0;
1853     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1854     {
1855         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1856         value.dwValueType = unicodeResults[i].valueType;
1857         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1858          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1859         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1860          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1861         if (buf)
1862         {
1863             ok(size == unicodeResults[i].encoded.cbData,
1864              "Value type %d: expected size %d, got %d\n",
1865              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1866             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1867              "Value type %d: unexpected value\n", value.dwValueType);
1868             LocalFree(buf);
1869         }
1870     }
1871     /* These "encode," but they do so by truncating each unicode character
1872      * rather than properly encoding it.  Kept separate from the proper results,
1873      * because the encoded forms won't decode to their original strings.
1874      */
1875     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1876     {
1877         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1878         value.dwValueType = unicodeWeirdness[i].valueType;
1879         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1880          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1881         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1882         if (buf)
1883         {
1884             ok(size == unicodeWeirdness[i].encoded.cbData,
1885              "Value type %d: expected size %d, got %d\n",
1886              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1887             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1888              "Value type %d: unexpected value\n", value.dwValueType);
1889             LocalFree(buf);
1890         }
1891     }
1892 }
1893
1894 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1895 {
1896     if (n <= 0) return 0;
1897     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1898     return *str1 - *str2;
1899 }
1900
1901 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1902 {
1903     DWORD i;
1904
1905     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1906     {
1907         BYTE *buf = NULL;
1908         BOOL ret;
1909         DWORD size = 0;
1910
1911         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1912          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1913          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1914         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1915          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1916         if (ret && buf)
1917         {
1918             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1919
1920             ok(value->dwValueType == unicodeResults[i].valueType,
1921              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1922              value->dwValueType);
1923             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1924              value->Value.cbData / sizeof(WCHAR)),
1925              "Unexpected decoded value for index %d (value type %d)\n", i,
1926              unicodeResults[i].valueType);
1927             LocalFree(buf);
1928         }
1929     }
1930 }
1931
1932 struct encodedOctets
1933 {
1934     const BYTE *val;
1935     const BYTE *encoded;
1936 };
1937
1938 static const unsigned char bin46[] = { 'h','i',0 };
1939 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1940 static const unsigned char bin48[] = {
1941      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1942 static const unsigned char bin49[] = {
1943      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1944 static const unsigned char bin50[] = { 0 };
1945 static const unsigned char bin51[] = { 0x04,0x00,0 };
1946
1947 static const struct encodedOctets octets[] = {
1948     { bin46, bin47 },
1949     { bin48, bin49 },
1950     { bin50, bin51 },
1951 };
1952
1953 static void test_encodeOctets(DWORD dwEncoding)
1954 {
1955     CRYPT_DATA_BLOB blob;
1956     DWORD i;
1957
1958     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1959     {
1960         BYTE *buf = NULL;
1961         BOOL ret;
1962         DWORD bufSize = 0;
1963
1964         blob.cbData = strlen((const char*)octets[i].val);
1965         blob.pbData = (BYTE*)octets[i].val;
1966         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1967          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1968         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1969         if (buf)
1970         {
1971             ok(buf[0] == 4,
1972              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1973             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1974              buf[1], octets[i].encoded[1]);
1975             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1976              octets[i].encoded[1] + 1), "Got unexpected value\n");
1977             LocalFree(buf);
1978         }
1979     }
1980 }
1981
1982 static void test_decodeOctets(DWORD dwEncoding)
1983 {
1984     DWORD i;
1985
1986     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1987     {
1988         BYTE *buf = NULL;
1989         BOOL ret;
1990         DWORD bufSize = 0;
1991
1992         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1993          octets[i].encoded, octets[i].encoded[1] + 2,
1994          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1995         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1996         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1997          "Expected size >= %d, got %d\n",
1998            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1999         ok(buf != NULL, "Expected allocated buffer\n");
2000         if (buf)
2001         {
2002             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2003
2004             if (blob->cbData)
2005                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2006                  "Unexpected value\n");
2007             LocalFree(buf);
2008         }
2009     }
2010 }
2011
2012 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2013
2014 struct encodedBits
2015 {
2016     DWORD cUnusedBits;
2017     const BYTE *encoded;
2018     DWORD cbDecoded;
2019     const BYTE *decoded;
2020 };
2021
2022 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2023 static const unsigned char bin53[] = { 0xff,0xff };
2024 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2025 static const unsigned char bin55[] = { 0xff,0xfe };
2026 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2027 static const unsigned char bin57[] = { 0xfe };
2028 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2029
2030 static const struct encodedBits bits[] = {
2031     /* normal test cases */
2032     { 0, bin52, 2, bin53 },
2033     { 1, bin54, 2, bin55 },
2034     /* strange test case, showing cUnusedBits >= 8 is allowed */
2035     { 9, bin56, 1, bin57 },
2036 };
2037
2038 static void test_encodeBits(DWORD dwEncoding)
2039 {
2040     DWORD i;
2041
2042     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2043     {
2044         CRYPT_BIT_BLOB blob;
2045         BOOL ret;
2046         BYTE *buf = NULL;
2047         DWORD bufSize = 0;
2048
2049         blob.cbData = sizeof(bytesToEncode);
2050         blob.pbData = (BYTE *)bytesToEncode;
2051         blob.cUnusedBits = bits[i].cUnusedBits;
2052         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2053          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2054         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2055         if (buf)
2056         {
2057             ok(bufSize == bits[i].encoded[1] + 2,
2058              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2059              bits[i].encoded[1] + 2);
2060             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2061              "%d: Unexpected value\n", i);
2062             LocalFree(buf);
2063         }
2064     }
2065 }
2066
2067 static void test_decodeBits(DWORD dwEncoding)
2068 {
2069     static const BYTE ber[] = "\x03\x02\x01\xff";
2070     static const BYTE berDecoded = 0xfe;
2071     DWORD i;
2072     BOOL ret;
2073     BYTE *buf = NULL;
2074     DWORD bufSize = 0;
2075
2076     /* normal cases */
2077     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2078     {
2079         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2080          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2081          &bufSize);
2082         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2083         if (buf)
2084         {
2085             CRYPT_BIT_BLOB *blob;
2086
2087             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2088                "Got unexpected size %d\n", bufSize);
2089             blob = (CRYPT_BIT_BLOB *)buf;
2090             ok(blob->cbData == bits[i].cbDecoded,
2091              "Got unexpected length %d, expected %d\n", blob->cbData,
2092              bits[i].cbDecoded);
2093             if (blob->cbData && bits[i].cbDecoded)
2094                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2095                  "Unexpected value\n");
2096             LocalFree(buf);
2097         }
2098     }
2099     /* special case: check that something that's valid in BER but not in DER
2100      * decodes successfully
2101      */
2102     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2103      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2104     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2105     if (buf)
2106     {
2107         CRYPT_BIT_BLOB *blob;
2108
2109         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2110            "Got unexpected size %d\n", bufSize);
2111         blob = (CRYPT_BIT_BLOB *)buf;
2112         ok(blob->cbData == sizeof(berDecoded),
2113            "Got unexpected length %d\n", blob->cbData);
2114         if (blob->cbData)
2115             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2116         LocalFree(buf);
2117     }
2118 }
2119
2120 struct Constraints2
2121 {
2122     CERT_BASIC_CONSTRAINTS2_INFO info;
2123     const BYTE *encoded;
2124 };
2125
2126 static const unsigned char bin59[] = { 0x30,0x00 };
2127 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2128 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2129 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2130 static const struct Constraints2 constraints2[] = {
2131  /* empty constraints */
2132  { { FALSE, FALSE, 0}, bin59 },
2133  /* can be a CA */
2134  { { TRUE,  FALSE, 0}, bin60 },
2135  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2136   * but that's not the case
2137   */
2138  { { FALSE, TRUE,  0}, bin61 },
2139  /* can be a CA and has path length constraints set */
2140  { { TRUE,  TRUE,  1}, bin62 },
2141 };
2142
2143 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2144 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2145  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2146  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2147  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2148 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2149  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2150  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2151  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2152  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2153
2154 static void test_encodeBasicConstraints(DWORD dwEncoding)
2155 {
2156     DWORD i, bufSize = 0;
2157     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2158     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2159      (LPBYTE)encodedDomainName };
2160     BOOL ret;
2161     BYTE *buf = NULL;
2162
2163     /* First test with the simpler info2 */
2164     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2165     {
2166         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2167          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2168          &bufSize);
2169         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2170         if (buf)
2171         {
2172             ok(bufSize == constraints2[i].encoded[1] + 2,
2173              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2174              bufSize);
2175             ok(!memcmp(buf, constraints2[i].encoded,
2176              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2177             LocalFree(buf);
2178         }
2179     }
2180     /* Now test with more complex basic constraints */
2181     info.SubjectType.cbData = 0;
2182     info.fPathLenConstraint = FALSE;
2183     info.cSubtreesConstraint = 0;
2184     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2185      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2186     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2187      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2188     if (buf)
2189     {
2190         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2191         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2192          "Unexpected value\n");
2193         LocalFree(buf);
2194     }
2195     /* None of the certs I examined had any subtree constraint, but I test one
2196      * anyway just in case.
2197      */
2198     info.cSubtreesConstraint = 1;
2199     info.rgSubtreesConstraint = &nameBlob;
2200     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2201      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2202     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2203      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2204     if (buf)
2205     {
2206         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2207         ok(!memcmp(buf, constraintWithDomainName,
2208          sizeof(constraintWithDomainName)), "Unexpected value\n");
2209         LocalFree(buf);
2210     }
2211     /* FIXME: test encoding with subject type. */
2212 }
2213
2214 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2215
2216 static void test_decodeBasicConstraints(DWORD dwEncoding)
2217 {
2218     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2219      0xff };
2220     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2221     DWORD i;
2222     BOOL ret;
2223     BYTE *buf = NULL;
2224     DWORD bufSize = 0;
2225
2226     /* First test with simpler info2 */
2227     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2228     {
2229         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2230          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2231          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2232         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2233          GetLastError());
2234         if (buf)
2235         {
2236             CERT_BASIC_CONSTRAINTS2_INFO *info =
2237              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2238
2239             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2240              "Unexpected value for item %d\n", i);
2241             LocalFree(buf);
2242         }
2243     }
2244     /* Check with the order of encoded elements inverted */
2245     buf = (PBYTE)1;
2246     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2247      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2248      &bufSize);
2249     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2250      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2251      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2252      GetLastError());
2253     ok(!buf, "Expected buf to be set to NULL\n");
2254     /* Check with a non-DER bool */
2255     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2256      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2257      &buf, &bufSize);
2258     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2259     if (buf)
2260     {
2261         CERT_BASIC_CONSTRAINTS2_INFO *info =
2262          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2263
2264         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2265         LocalFree(buf);
2266     }
2267     /* Check with a non-basic constraints value */
2268     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2269      encodedCommonName, encodedCommonName[1] + 2,
2270      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2271     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2272      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2273      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2274      GetLastError());
2275     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2276     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2277      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2278      &buf, &bufSize);
2279     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2280     if (buf)
2281     {
2282         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2283
2284         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2285         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2286         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2287         LocalFree(buf);
2288     }
2289     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2290      constraintWithDomainName, sizeof(constraintWithDomainName),
2291      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2292     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2293     if (buf)
2294     {
2295         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2296
2297         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2298         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2299         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2300         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2301         {
2302             ok(info->rgSubtreesConstraint[0].cbData ==
2303              sizeof(encodedDomainName), "Wrong size %d\n",
2304              info->rgSubtreesConstraint[0].cbData);
2305             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2306              sizeof(encodedDomainName)), "Unexpected value\n");
2307         }
2308         LocalFree(buf);
2309     }
2310 }
2311
2312 /* These are terrible public keys of course, I'm just testing encoding */
2313 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2314 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2315 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2316 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2317 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2318 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2319 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2320 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2321
2322 struct EncodedRSAPubKey
2323 {
2324     const BYTE *modulus;
2325     size_t modulusLen;
2326     const BYTE *encoded;
2327     size_t decodedModulusLen;
2328 };
2329
2330 struct EncodedRSAPubKey rsaPubKeys[] = {
2331     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2332     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2333     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2334     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2335 };
2336
2337 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2338 {
2339     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2340     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2341     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2342     BOOL ret;
2343     BYTE *buf = NULL;
2344     DWORD bufSize = 0, i;
2345
2346     /* Try with a bogus blob type */
2347     hdr->bType = 2;
2348     hdr->bVersion = CUR_BLOB_VERSION;
2349     hdr->reserved = 0;
2350     hdr->aiKeyAlg = CALG_RSA_KEYX;
2351     rsaPubKey->magic = 0x31415352;
2352     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2353     rsaPubKey->pubexp = 65537;
2354     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2355      sizeof(modulus1));
2356
2357     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2358      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2359     ok(!ret && GetLastError() == E_INVALIDARG,
2360      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2361     /* Now with a bogus reserved field */
2362     hdr->bType = PUBLICKEYBLOB;
2363     hdr->reserved = 1;
2364     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2365      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2366     if (buf)
2367     {
2368         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2369          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2370         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2371         LocalFree(buf);
2372     }
2373     /* Now with a bogus blob version */
2374     hdr->reserved = 0;
2375     hdr->bVersion = 0;
2376     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2377      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2378     if (buf)
2379     {
2380         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2381          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2382         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2383         LocalFree(buf);
2384     }
2385     /* And with a bogus alg ID */
2386     hdr->bVersion = CUR_BLOB_VERSION;
2387     hdr->aiKeyAlg = CALG_DES;
2388     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2389      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2390     if (buf)
2391     {
2392         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2393          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2394         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2395         LocalFree(buf);
2396     }
2397     /* Check a couple of RSA-related OIDs */
2398     hdr->aiKeyAlg = CALG_RSA_KEYX;
2399     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2400      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2401     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2402      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2403     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2404      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2405     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2406      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2407     /* Finally, all valid */
2408     hdr->aiKeyAlg = CALG_RSA_KEYX;
2409     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2410     {
2411         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2412          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2413         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2414          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2415         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2416         if (buf)
2417         {
2418             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2419              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2420              bufSize);
2421             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2422              "Unexpected value\n");
2423             LocalFree(buf);
2424         }
2425     }
2426 }
2427
2428 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2429 {
2430     DWORD i;
2431     LPBYTE buf = NULL;
2432     DWORD bufSize = 0;
2433     BOOL ret;
2434
2435     /* Try with a bad length */
2436     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2437      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2438      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2439     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2440      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2441      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2442      GetLastError());
2443     /* Try with a couple of RSA-related OIDs */
2444     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2445      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2446      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2447     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2448      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2449     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2450      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2451      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2452     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2453      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2454     /* Now try success cases */
2455     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2456     {
2457         bufSize = 0;
2458         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2459          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2460          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2461         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2462         if (buf)
2463         {
2464             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2465             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2466
2467             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2468              rsaPubKeys[i].decodedModulusLen,
2469              "Wrong size %d\n", bufSize);
2470             ok(hdr->bType == PUBLICKEYBLOB,
2471              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2472              hdr->bType);
2473             ok(hdr->bVersion == CUR_BLOB_VERSION,
2474              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2475              CUR_BLOB_VERSION, hdr->bVersion);
2476             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2477              hdr->reserved);
2478             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2479              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2480             ok(rsaPubKey->magic == 0x31415352,
2481              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2482             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2483              "Wrong bit len %d\n", rsaPubKey->bitlen);
2484             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2485              rsaPubKey->pubexp);
2486             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2487              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2488              "Unexpected modulus\n");
2489             LocalFree(buf);
2490         }
2491     }
2492 }
2493
2494 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2495  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2496  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2497
2498 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2499  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2500  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2501  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2502
2503 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2504 {
2505     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2506     CRYPT_SEQUENCE_OF_ANY seq;
2507     DWORD i;
2508     BOOL ret;
2509     BYTE *buf = NULL;
2510     DWORD bufSize = 0;
2511
2512     /* Encode a homogeneous sequence */
2513     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2514     {
2515         blobs[i].cbData = ints[i].encoded[1] + 2;
2516         blobs[i].pbData = (BYTE *)ints[i].encoded;
2517     }
2518     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2519     seq.rgValue = blobs;
2520
2521     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2522      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2523     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2524     if (buf)
2525     {
2526         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2527         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2528         LocalFree(buf);
2529     }
2530     /* Change the type of the first element in the sequence, and give it
2531      * another go
2532      */
2533     blobs[0].cbData = times[0].encodedTime[1] + 2;
2534     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2535     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2536      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2537     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2538     if (buf)
2539     {
2540         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2541         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2542          "Unexpected value\n");
2543         LocalFree(buf);
2544     }
2545 }
2546
2547 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2548 {
2549     BOOL ret;
2550     BYTE *buf = NULL;
2551     DWORD bufSize = 0;
2552
2553     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2554      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2555     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2556     if (buf)
2557     {
2558         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2559         DWORD i;
2560
2561         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2562          "Wrong elements %d\n", seq->cValue);
2563         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2564         {
2565             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2566              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2567              seq->rgValue[i].cbData);
2568             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2569              ints[i].encoded[1] + 2), "Unexpected value\n");
2570         }
2571         LocalFree(buf);
2572     }
2573     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2574      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2575      &bufSize);
2576     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2577     if (buf)
2578     {
2579         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2580
2581         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2582          "Wrong elements %d\n", seq->cValue);
2583         /* Just check the first element since it's all that changed */
2584         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2585          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2586          seq->rgValue[0].cbData);
2587         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2588          times[0].encodedTime[1] + 2), "Unexpected value\n");
2589         LocalFree(buf);
2590     }
2591 }
2592
2593 struct encodedExtensions
2594 {
2595     CERT_EXTENSIONS exts;
2596     const BYTE *encoded;
2597 };
2598
2599 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2600 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2601 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2602 static CERT_EXTENSION criticalExt =
2603  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2604 static CERT_EXTENSION nonCriticalExt =
2605  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2606 static CHAR oid_short[] = "1.1";
2607 static CERT_EXTENSION extWithShortOid =
2608  { oid_short, FALSE, { 0, NULL } };
2609
2610 static const BYTE ext0[] = { 0x30,0x00 };
2611 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2612                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2613 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2614                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2615 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2616
2617 static const struct encodedExtensions exts[] = {
2618  { { 0, NULL }, ext0 },
2619  { { 1, &criticalExt }, ext1 },
2620  { { 1, &nonCriticalExt }, ext2 },
2621  { { 1, &extWithShortOid }, ext3 }
2622 };
2623
2624 static void test_encodeExtensions(DWORD dwEncoding)
2625 {
2626     DWORD i;
2627
2628     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2629     {
2630         BOOL ret;
2631         BYTE *buf = NULL;
2632         DWORD bufSize = 0;
2633
2634         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2635          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2636         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2637         if (buf)
2638         {
2639             ok(bufSize == exts[i].encoded[1] + 2,
2640              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2641             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2642              "Unexpected value\n");
2643             LocalFree(buf);
2644         }
2645     }
2646 }
2647
2648 static void test_decodeExtensions(DWORD dwEncoding)
2649 {
2650     DWORD i;
2651
2652     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2653     {
2654         BOOL ret;
2655         BYTE *buf = NULL;
2656         DWORD bufSize = 0;
2657
2658         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2659          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2660          NULL, &buf, &bufSize);
2661         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2662         if (buf)
2663         {
2664             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2665             DWORD j;
2666
2667             ok(ext->cExtension == exts[i].exts.cExtension,
2668              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2669              ext->cExtension);
2670             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2671             {
2672                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2673                  exts[i].exts.rgExtension[j].pszObjId),
2674                  "Expected OID %s, got %s\n",
2675                  exts[i].exts.rgExtension[j].pszObjId,
2676                  ext->rgExtension[j].pszObjId);
2677                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2678                  exts[i].exts.rgExtension[j].Value.pbData,
2679                  exts[i].exts.rgExtension[j].Value.cbData),
2680                  "Unexpected value\n");
2681             }
2682             LocalFree(buf);
2683         }
2684     }
2685 }
2686
2687 /* MS encodes public key info with a NULL if the algorithm identifier's
2688  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2689  * it encodes them by omitting the algorithm parameters.  It accepts either
2690  * form for decoding.
2691  */
2692 struct encodedPublicKey
2693 {
2694     CERT_PUBLIC_KEY_INFO info;
2695     const BYTE *encoded;
2696     const BYTE *encodedNoNull;
2697     CERT_PUBLIC_KEY_INFO decoded;
2698 };
2699
2700 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2701  0xe, 0xf };
2702 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2703
2704 static const unsigned char bin64[] = {
2705     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2706 static const unsigned char bin65[] = {
2707     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2708 static const unsigned char bin66[] = {
2709     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2710 static const unsigned char bin67[] = {
2711     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2712 static const unsigned char bin68[] = {
2713     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2714     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2715 static const unsigned char bin69[] = {
2716     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2717     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2718 static const unsigned char bin70[] = {
2719     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2720     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2721     0x0f};
2722 static const unsigned char bin71[] = {
2723     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2724     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2725     0x0f};
2726 static unsigned char bin72[] = { 0x05,0x00};
2727
2728 static CHAR oid_bogus[] = "1.2.3",
2729             oid_rsa[]   = szOID_RSA;
2730
2731 static const struct encodedPublicKey pubKeys[] = {
2732  /* with a bogus OID */
2733  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2734   bin64, bin65,
2735   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2736  /* some normal keys */
2737  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2738   bin66, bin67,
2739   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2740  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2741   bin68, bin69,
2742   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2743  /* with add'l parameters--note they must be DER-encoded */
2744  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2745   (BYTE *)aKey, 0 } },
2746   bin70, bin71,
2747   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2748   (BYTE *)aKey, 0 } } },
2749 };
2750
2751 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2752 {
2753     DWORD i;
2754
2755     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2756     {
2757         BOOL ret;
2758         BYTE *buf = NULL;
2759         DWORD bufSize = 0;
2760
2761         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2762          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2763          &bufSize);
2764         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2765          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2766         if (buf)
2767         {
2768             ok(bufSize == pubKeys[i].encoded[1] + 2,
2769              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2770             if (bufSize == pubKeys[i].encoded[1] + 2)
2771                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2772                  "Unexpected value\n");
2773             LocalFree(buf);
2774         }
2775     }
2776 }
2777
2778 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2779  const CERT_PUBLIC_KEY_INFO *got)
2780 {
2781     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2782      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2783      got->Algorithm.pszObjId);
2784     ok(expected->Algorithm.Parameters.cbData ==
2785      got->Algorithm.Parameters.cbData,
2786      "Expected parameters of %d bytes, got %d\n",
2787      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2788     if (expected->Algorithm.Parameters.cbData)
2789         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2790          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2791          "Unexpected algorithm parameters\n");
2792     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2793      "Expected public key of %d bytes, got %d\n",
2794      expected->PublicKey.cbData, got->PublicKey.cbData);
2795     if (expected->PublicKey.cbData)
2796         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2797          got->PublicKey.cbData), "Unexpected public key value\n");
2798 }
2799
2800 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2801 {
2802     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2803      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2804      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2805      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2806     DWORD i;
2807     BOOL ret;
2808     BYTE *buf = NULL;
2809     DWORD bufSize = 0;
2810
2811     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2812     {
2813         /* The NULL form decodes to the decoded member */
2814         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2815          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2816          NULL, &buf, &bufSize);
2817         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2818         if (buf)
2819         {
2820             comparePublicKeyInfo(&pubKeys[i].decoded,
2821              (CERT_PUBLIC_KEY_INFO *)buf);
2822             LocalFree(buf);
2823         }
2824         /* The non-NULL form decodes to the original */
2825         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2826          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2827          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2828         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2829         if (buf)
2830         {
2831             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2832             LocalFree(buf);
2833         }
2834     }
2835     /* Test with bogus (not valid DER) parameters */
2836     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2837      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2838      NULL, &buf, &bufSize);
2839     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2840      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2841      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2842      GetLastError());
2843 }
2844
2845 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2846  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2847  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2848  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2849  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2850 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2851  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2852  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2853  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2854  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2855 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2856  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2857  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2858  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2859  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2860 static const BYTE v4Cert[] = {
2861 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2862 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2863 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2864 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2865 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2866  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2867  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2868  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2869  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2870  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2871  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2872 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2873  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2874  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2875  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2876  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2877  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2878  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2879 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2880  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2881  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2882  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2883  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2884  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2885  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2886  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2887  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2888  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2889 static const BYTE v1CertWithPubKey[] = {
2890 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2891 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2892 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2893 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2894 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2895 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2896 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2897 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2898 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2899 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2900 0x01,0x01 };
2901 static const BYTE v1CertWithPubKeyNoNull[] = {
2902 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2903 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2904 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2905 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2906 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2907 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2908 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2909 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2910 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2911 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2912 static const BYTE v1CertWithSubjectKeyId[] = {
2913 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2914 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2915 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2916 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2917 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2918 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2919 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2920 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2921 0x4c,0x61,0x6e,0x67,0x00 };
2922 static const BYTE v1CertWithIssuerUniqueId[] = {
2923 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2924 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2925 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2926 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2927 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2928 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2929 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2930 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2931 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2932 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2933 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2934 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2935 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2936 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2937 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2938 0x01,0x01,0xff,0x02,0x01,0x01 };
2939 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2940 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2941 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2942 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2943 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2944 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2945 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2946 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2947 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2948 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2949 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2950 0xff,0x02,0x01,0x01 };
2951
2952 static const BYTE serialNum[] = { 0x01 };
2953
2954 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2955 {
2956     BOOL ret;
2957     BYTE *buf = NULL;
2958     DWORD size = 0;
2959     CERT_INFO info = { 0 };
2960     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2961     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2962     CERT_EXTENSION ext;
2963
2964     if (0)
2965     {
2966         /* Test with NULL pvStructInfo (crashes on win9x) */
2967         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2968          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2969         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2970          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2971     }
2972     /* Test with a V1 cert */
2973     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2974      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2975     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2976      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2977     if (buf)
2978     {
2979         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2980          v1Cert[1] + 2, size);
2981         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2982         LocalFree(buf);
2983     }
2984     /* Test v2 cert */
2985     info.dwVersion = CERT_V2;
2986     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2987      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2988     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2989      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2990     if (buf)
2991     {
2992         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2993         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2994         LocalFree(buf);
2995     }
2996     /* Test v3 cert */
2997     info.dwVersion = CERT_V3;
2998     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2999      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3000     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3001      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3002     if (buf)
3003     {
3004         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3005         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3006         LocalFree(buf);
3007     }
3008     /* A v4 cert? */
3009     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3010     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3011      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3012     if (buf)
3013     {
3014         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3015         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3016         LocalFree(buf);
3017     }
3018     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3019      * API doesn't prevent it)
3020      */
3021     info.dwVersion = CERT_V1;
3022     info.cExtension = 1;
3023     info.rgExtension = &criticalExt;
3024     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3025      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3026     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3027      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3028     if (buf)
3029     {
3030         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3031         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3032         LocalFree(buf);
3033     }
3034     /* test v1 cert with a serial number */
3035     info.SerialNumber.cbData = sizeof(serialNum);
3036     info.SerialNumber.pbData = (BYTE *)serialNum;
3037     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3038      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3039     if (buf)
3040     {
3041         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3042         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3043         LocalFree(buf);
3044     }
3045     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3046     info.dwVersion = CERT_V1;
3047     info.cExtension = 0;
3048     info.IssuerUniqueId.cbData = sizeof(serialNum);
3049     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3050     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3051      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3052     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3053     if (buf)
3054     {
3055         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3056         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3057          "Got unexpected value\n");
3058         LocalFree(buf);
3059     }
3060     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3061     info.IssuerUniqueId.cbData = 0;
3062     info.IssuerUniqueId.pbData = NULL;
3063     info.cExtension = 1;
3064     info.rgExtension = &criticalExt;
3065     info.Issuer.cbData = sizeof(encodedCommonName);
3066     info.Issuer.pbData = (BYTE *)encodedCommonName;
3067     info.Subject.cbData = sizeof(encodedCommonName);
3068     info.Subject.pbData = (BYTE *)encodedCommonName;
3069     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3070      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3071     if (buf)
3072     {
3073         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3074         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3075         LocalFree(buf);
3076     }
3077     /* Add a public key */
3078     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3079     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3080     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3081     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3082      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3083     if (buf)
3084     {
3085         ok(size == sizeof(v1CertWithPubKey) ||
3086          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3087         if (size == sizeof(v1CertWithPubKey))
3088             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3089         else if (size == sizeof(v1CertWithPubKeyNoNull))
3090             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3091              "Got unexpected value\n");
3092         LocalFree(buf);
3093     }
3094     /* Again add an issuer unique id */
3095     info.IssuerUniqueId.cbData = sizeof(serialNum);
3096     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3097     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3098      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3099     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3100     if (buf)
3101     {
3102         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3103          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3104          "Wrong size %d\n", size);
3105         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3106             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3107              size), "unexpected value\n");
3108         else if (size ==
3109          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3110             ok(!memcmp(buf,
3111              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3112              "unexpected value\n");
3113         LocalFree(buf);
3114     }
3115     /* Remove the public key, and add a subject key identifier extension */
3116     info.IssuerUniqueId.cbData = 0;
3117     info.IssuerUniqueId.pbData = NULL;
3118     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3119     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3120     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3121     ext.pszObjId = oid_subject_key_identifier;
3122     ext.fCritical = FALSE;
3123     ext.Value.cbData = sizeof(octetCommonNameValue);
3124     ext.Value.pbData = octetCommonNameValue;
3125     info.cExtension = 1;
3126     info.rgExtension = &ext;
3127     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3128      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3129     if (buf)
3130     {
3131         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3132         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3133         LocalFree(buf);
3134     }
3135 }
3136
3137 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3138 {
3139     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3140      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3141     BOOL ret;
3142     BYTE *buf = NULL;
3143     DWORD size = 0, i;
3144
3145     /* Test with NULL pbEncoded */
3146     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3147      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3148     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3149      GetLastError() == OSS_BAD_ARG /* Win9x */),
3150      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3151     if (0)
3152     {
3153         /* Crashes on win9x */
3154         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3155          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3156         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3157          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3158     }
3159     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3160      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3161      * serial number, an issuer, a subject, and a public key.
3162      */
3163     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3164     {
3165         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3166          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3167          &buf, &size);
3168         ok(!ret, "Expected failure\n");
3169     }
3170     /* The following succeeds, even though v1 certs are not allowed to have
3171      * extensions.
3172      */
3173     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3174      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3175      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3176     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3177     if (ret)
3178     {
3179         CERT_INFO *info = (CERT_INFO *)buf;
3180
3181         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3182         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3183          info->dwVersion);
3184         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3185          info->cExtension);
3186         LocalFree(buf);
3187     }
3188     /* The following also succeeds, even though V1 certs are not allowed to
3189      * have issuer unique ids.
3190      */
3191     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3192      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3193      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3194      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3196     if (ret)
3197     {
3198         CERT_INFO *info = (CERT_INFO *)buf;
3199
3200         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3201         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3202          info->dwVersion);
3203         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3204          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3205         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3206          "unexpected issuer unique id value\n");
3207         LocalFree(buf);
3208     }
3209     /* Now check with serial number, subject and issuer specified */
3210     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3211      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3212     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3213     if (buf)
3214     {
3215         CERT_INFO *info = (CERT_INFO *)buf;
3216
3217         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3218         ok(info->SerialNumber.cbData == 1,
3219          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3220         ok(*info->SerialNumber.pbData == *serialNum,
3221          "Expected serial number %d, got %d\n", *serialNum,
3222          *info->SerialNumber.pbData);
3223         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3224          "Wrong size %d\n", info->Issuer.cbData);
3225         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3226          "Unexpected issuer\n");
3227         ok(info->Subject.cbData == sizeof(encodedCommonName),
3228          "Wrong size %d\n", info->Subject.cbData);
3229         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3230          info->Subject.cbData), "Unexpected subject\n");
3231         LocalFree(buf);
3232     }
3233     /* Check again with pub key specified */
3234     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3235      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3236      &buf, &size);
3237     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3238     if (buf)
3239     {
3240         CERT_INFO *info = (CERT_INFO *)buf;
3241
3242         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3243         ok(info->SerialNumber.cbData == 1,
3244          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3245         ok(*info->SerialNumber.pbData == *serialNum,
3246          "Expected serial number %d, got %d\n", *serialNum,
3247          *info->SerialNumber.pbData);
3248         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3249          "Wrong size %d\n", info->Issuer.cbData);
3250         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3251          "Unexpected issuer\n");
3252         ok(info->Subject.cbData == sizeof(encodedCommonName),
3253          "Wrong size %d\n", info->Subject.cbData);
3254         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3255          info->Subject.cbData), "Unexpected subject\n");
3256         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3257          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3258          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3259         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3260          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3261         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3262          sizeof(aKey)), "Unexpected public key\n");
3263         LocalFree(buf);
3264     }
3265 }
3266
3267 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3268  0xe, 0xf };
3269
3270 static const BYTE signedBigCert[] = {
3271  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3272  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3273  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3274  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3275  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3276  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3277  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3278  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3279  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3280  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3281  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3282  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3283
3284 static void test_encodeCert(DWORD dwEncoding)
3285 {
3286     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3287      * also that bigCert is a NULL-terminated string, so don't count its
3288      * last byte (otherwise the signed cert won't decode.)
3289      */
3290     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3291      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3292     BOOL ret;
3293     BYTE *buf = NULL;
3294     DWORD bufSize = 0;
3295
3296     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3297      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3298     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3299     if (buf)
3300     {
3301         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3302         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3303         LocalFree(buf);
3304     }
3305 }
3306
3307 static void test_decodeCert(DWORD dwEncoding)
3308 {
3309     BOOL ret;
3310     BYTE *buf = NULL;
3311     DWORD size = 0;
3312
3313     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3314      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3315     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3316     if (buf)
3317     {
3318         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3319
3320         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3321          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3322         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3323          "Unexpected cert\n");
3324         ok(info->Signature.cbData == sizeof(hash),
3325          "Wrong signature size %d\n", info->Signature.cbData);
3326         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3327          "Unexpected signature\n");
3328         LocalFree(buf);
3329     }
3330     /* A signed cert decodes as a CERT_INFO too */
3331     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3332      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3333     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3334     if (buf)
3335     {
3336         CERT_INFO *info = (CERT_INFO *)buf;
3337
3338         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3339         ok(info->SerialNumber.cbData == 1,
3340          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3341         ok(*info->SerialNumber.pbData == *serialNum,
3342          "Expected serial number %d, got %d\n", *serialNum,
3343          *info->SerialNumber.pbData);
3344         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3345          "Wrong size %d\n", info->Issuer.cbData);
3346         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3347          "Unexpected issuer\n");
3348         ok(info->Subject.cbData == sizeof(encodedCommonName),
3349          "Wrong size %d\n", info->Subject.cbData);
3350         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3351          info->Subject.cbData), "Unexpected subject\n");
3352         LocalFree(buf);
3353     }
3354 }
3355
3356 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3357 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3358  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3359  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3360 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3361  0x00, 0x03 };
3362 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3363  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3364  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3365 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3366  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3367  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3368  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3369  0x2e, 0x6f, 0x72, 0x67 };
3370 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3371  CRL_REASON_AFFILIATION_CHANGED;
3372
3373 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3374 {
3375     CRL_DIST_POINTS_INFO info = { 0 };
3376     CRL_DIST_POINT point = { { 0 } };
3377     CERT_ALT_NAME_ENTRY entry = { 0 };
3378     BOOL ret;
3379     BYTE *buf = NULL;
3380     DWORD size = 0;
3381
3382     /* Test with an empty info */
3383     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3384      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3385     ok(!ret && GetLastError() == E_INVALIDARG,
3386      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3387     /* Test with one empty dist point */
3388     info.cDistPoint = 1;
3389     info.rgDistPoint = &point;
3390     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3391      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3392     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3393     if (buf)
3394     {
3395         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3396         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3397         LocalFree(buf);
3398     }
3399     /* A dist point with an invalid name */
3400     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3401     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3402     U(entry).pwszURL = (LPWSTR)nihongoURL;
3403     U(point.DistPointName).FullName.cAltEntry = 1;
3404     U(point.DistPointName).FullName.rgAltEntry = &entry;
3405     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3406      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3407     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3408      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3409     /* The first invalid character is at index 7 */
3410     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3411      "Expected invalid char at index 7, got %d\n",
3412      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3413     /* A dist point with (just) a valid name */
3414     U(entry).pwszURL = (LPWSTR)url;
3415     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3416      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3417     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3418     if (buf)
3419     {
3420         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3421         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3422         LocalFree(buf);
3423     }
3424     /* A dist point with (just) reason flags */
3425     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3426     point.ReasonFlags.cbData = sizeof(crlReason);
3427     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3428     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3429      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3430     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3431     if (buf)
3432     {
3433         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3434         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3435         LocalFree(buf);
3436     }
3437     /* A dist point with just an issuer */
3438     point.ReasonFlags.cbData = 0;
3439     point.CRLIssuer.cAltEntry = 1;
3440     point.CRLIssuer.rgAltEntry = &entry;
3441     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3442      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3443     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3444     if (buf)
3445     {
3446         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3447         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3448         LocalFree(buf);
3449     }
3450     /* A dist point with both a name and an issuer */
3451     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3452     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3454     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3455     if (buf)
3456     {
3457         ok(size == sizeof(distPointWithUrlAndIssuer),
3458          "Wrong size %d\n", size);
3459         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3460         LocalFree(buf);
3461     }
3462 }
3463
3464 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3465 {
3466     BOOL ret;
3467     BYTE *buf = NULL;
3468     DWORD size = 0;
3469     PCRL_DIST_POINTS_INFO info;
3470     PCRL_DIST_POINT point;
3471     PCERT_ALT_NAME_ENTRY entry;
3472
3473     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3474      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3475      &buf, &size);
3476     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3477     if (ret)
3478     {
3479         info = (PCRL_DIST_POINTS_INFO)buf;
3480         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3481          "Wrong size %d\n", size);
3482         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3483          info->cDistPoint);
3484         point = info->rgDistPoint;
3485         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3486          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3487          point->DistPointName.dwDistPointNameChoice);
3488         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3489         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3490         LocalFree(buf);
3491     }
3492     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3493      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3494      &buf, &size);
3495     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3496     if (ret)
3497     {
3498         info = (PCRL_DIST_POINTS_INFO)buf;
3499         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3500          "Wrong size %d\n", size);
3501         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3502          info->cDistPoint);
3503         point = info->rgDistPoint;
3504         ok(point->DistPointName.dwDistPointNameChoice ==
3505          CRL_DIST_POINT_FULL_NAME,
3506          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3507          point->DistPointName.dwDistPointNameChoice);
3508         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3509          "Expected 1 name entry, got %d\n",
3510          U(point->DistPointName).FullName.cAltEntry);
3511         entry = U(point->DistPointName).FullName.rgAltEntry;
3512         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3513          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3514         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3515         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3516         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3517         LocalFree(buf);
3518     }
3519     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3520      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3521      NULL, &buf, &size);
3522     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3523     if (ret)
3524     {
3525         info = (PCRL_DIST_POINTS_INFO)buf;
3526         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3527          "Wrong size %d\n", size);
3528         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3529          info->cDistPoint);
3530         point = info->rgDistPoint;
3531         ok(point->DistPointName.dwDistPointNameChoice ==
3532          CRL_DIST_POINT_NO_NAME,
3533          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3534          point->DistPointName.dwDistPointNameChoice);
3535         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3536          "Expected reason length\n");
3537         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3538          "Unexpected reason\n");
3539         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3540         LocalFree(buf);
3541     }
3542     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3543      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3544      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3545     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3546     if (ret)
3547     {
3548         info = (PCRL_DIST_POINTS_INFO)buf;
3549         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3550          "Wrong size %d\n", size);
3551         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3552          info->cDistPoint);
3553         point = info->rgDistPoint;
3554         ok(point->DistPointName.dwDistPointNameChoice ==
3555          CRL_DIST_POINT_FULL_NAME,
3556          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3557          point->DistPointName.dwDistPointNameChoice);
3558         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3559          "Expected 1 name entry, got %d\n",
3560          U(point->DistPointName).FullName.cAltEntry);
3561         entry = U(point->DistPointName).FullName.rgAltEntry;
3562         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3563          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3564         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3565         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3566         ok(point->CRLIssuer.cAltEntry == 1,
3567          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3568         entry = point->CRLIssuer.rgAltEntry;
3569         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3570          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3571         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3572         LocalFree(buf);
3573     }
3574 }
3575
3576 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3577 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3578 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3579  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3580  0x67 };
3581
3582 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3583 {
3584     BOOL ret;
3585     BYTE *buf = NULL;
3586     DWORD size = 0;
3587     CRL_ISSUING_DIST_POINT point = { { 0 } };
3588     CERT_ALT_NAME_ENTRY entry;
3589
3590     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3591      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3592     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3593     {
3594         skip("no X509_ISSUING_DIST_POINT encode support\n");
3595         return;
3596     }
3597     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3598      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3599     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3600      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3601     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3602     if (buf)
3603     {
3604         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3605         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3606         LocalFree(buf);
3607     }
3608     /* nonsensical flags */
3609     point.fOnlyContainsUserCerts = TRUE;
3610     point.fOnlyContainsCACerts = TRUE;
3611     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3612      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3613     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3614     if (buf)
3615     {
3616         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3617         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3618         LocalFree(buf);
3619     }
3620     /* unimplemented name type */
3621     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3622     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3623     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3624      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3625     ok(!ret && GetLastError() == E_INVALIDARG,
3626      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3627     /* empty name */
3628     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3629     U(point.DistPointName).FullName.cAltEntry = 0;
3630     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3631      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3632     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3633     if (buf)
3634     {
3635         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3636         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3637         LocalFree(buf);
3638     }
3639     /* name with URL entry */
3640     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3641     U(entry).pwszURL = (LPWSTR)url;
3642     U(point.DistPointName).FullName.cAltEntry = 1;
3643     U(point.DistPointName).FullName.rgAltEntry = &entry;
3644     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3645      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3646     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3647     if (buf)
3648     {
3649         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3650         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3651         LocalFree(buf);
3652     }
3653 }
3654
3655 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3656  const CERT_ALT_NAME_ENTRY *got)
3657 {
3658     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3659      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3660      got->dwAltNameChoice);
3661     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3662     {
3663         switch (got->dwAltNameChoice)
3664         {
3665         case CERT_ALT_NAME_RFC822_NAME:
3666         case CERT_ALT_NAME_DNS_NAME:
3667         case CERT_ALT_NAME_EDI_PARTY_NAME:
3668         case CERT_ALT_NAME_URL:
3669         case CERT_ALT_NAME_REGISTERED_ID:
3670             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3671              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3672              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3673              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3674              "Unexpected name\n");
3675             break;
3676         case CERT_ALT_NAME_X400_ADDRESS:
3677         case CERT_ALT_NAME_DIRECTORY_NAME:
3678         case CERT_ALT_NAME_IP_ADDRESS:
3679             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3680                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3681             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3682                        U(*got).IPAddress.cbData), "Unexpected value\n");
3683             break;
3684         }
3685     }
3686 }
3687
3688 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3689  const CERT_ALT_NAME_INFO *got)
3690 {
3691     DWORD i;
3692
3693     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3694      expected->cAltEntry, got->cAltEntry);
3695     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3696         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3697 }
3698
3699 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3700  const CRL_DIST_POINT_NAME *got)
3701 {
3702     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3703      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3704     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3705         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3706 }
3707
3708 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3709  const CRL_ISSUING_DIST_POINT *got)
3710 {
3711     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3712     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3713      "Unexpected fOnlyContainsUserCerts\n");
3714     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3715      "Unexpected fOnlyContainsCACerts\n");
3716     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3717      "Unexpected reason flags\n");
3718     ok(got->fIndirectCRL == expected->fIndirectCRL,
3719      "Unexpected fIndirectCRL\n");
3720 }
3721
3722 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3723 {
3724     BOOL ret;
3725     BYTE *buf = NULL;
3726     DWORD size = 0;
3727     CRL_ISSUING_DIST_POINT point = { { 0 } };
3728
3729     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3730      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3731      &buf, &size);
3732     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3733     {
3734         skip("no X509_ISSUING_DIST_POINT decode support\n");
3735         return;
3736     }
3737     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3738     if (ret)
3739     {
3740         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3741         LocalFree(buf);
3742     }
3743     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3744      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3745      &buf, &size);
3746     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3747     if (ret)
3748     {
3749         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3750         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3751         LocalFree(buf);
3752     }
3753     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3754      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3755      &buf, &size);
3756     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3757     if (ret)
3758     {
3759         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3760         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3761         U(point.DistPointName).FullName.cAltEntry = 0;
3762         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3763         LocalFree(buf);
3764     }
3765     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3766      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3767     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3768     if (ret)
3769     {
3770         CERT_ALT_NAME_ENTRY entry;
3771
3772         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3773         U(entry).pwszURL = (LPWSTR)url;
3774         U(point.DistPointName).FullName.cAltEntry = 1;
3775         U(point.DistPointName).FullName.rgAltEntry = &entry;
3776         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3777         LocalFree(buf);
3778     }
3779 }
3780
3781 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3782  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3783  0x30, 0x5a };
3784 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3785  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3786  0x30, 0x30, 0x30, 0x30, 0x5a };
3787 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3788  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3789  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3790  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3791  0x5a };
3792 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3793  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3794  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3795  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3796  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3797  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3798 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3799  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3800  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3801  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3802  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3803  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3804 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3805  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3806  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3807  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3808  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3809  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3810  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3811 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3812  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3813  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3814  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3815  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3816  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3817  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3818 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3819  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3820  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3821  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3822  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3823  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3824  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3825 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3826  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3827  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3828  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3829  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3830  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3831  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3832
3833 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3834 {
3835     BOOL ret;
3836     BYTE *buf = NULL;
3837     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3838     DWORD size = 0;
3839     CRL_INFO info = { 0 };
3840     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3841     CERT_EXTENSION ext;
3842
3843     /* Test with a V1 CRL */
3844     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3845      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3846     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3847      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3848     if (buf)
3849     {
3850         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3851         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3852         LocalFree(buf);
3853     }
3854     /* Test v2 CRL */
3855     info.dwVersion = CRL_V2;
3856     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3857      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3858     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3859      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3860     if (buf)
3861     {
3862         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3863          v2CRL[1] + 2, size);
3864         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3865         LocalFree(buf);
3866     }
3867     /* v1 CRL with a name */
3868     info.dwVersion = CRL_V1;
3869     info.Issuer.cbData = sizeof(encodedCommonName);
3870     info.Issuer.pbData = (BYTE *)encodedCommonName;
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(v1CRLWithIssuer), "Wrong size %d\n", size);
3877         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3878         LocalFree(buf);
3879     }
3880     if (0)
3881     {
3882         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3883         info.cCRLEntry = 1;
3884         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3885          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3886         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3887          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3888     }
3889     /* now set an empty entry */
3890     info.cCRLEntry = 1;
3891     info.rgCRLEntry = &entry;
3892     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3893      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3894     if (buf)
3895     {
3896         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3897          "Wrong size %d\n", size);
3898         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3899          "Got unexpected value\n");
3900         LocalFree(buf);
3901     }
3902     /* an entry with a serial number */
3903     entry.SerialNumber.cbData = sizeof(serialNum);
3904     entry.SerialNumber.pbData = (BYTE *)serialNum;
3905     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3906      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3907     if (buf)
3908     {
3909         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3910          "Wrong size %d\n", size);
3911         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3912          "Got unexpected value\n");
3913         LocalFree(buf);
3914     }
3915     /* an entry with an extension */
3916     entry.cExtension = 1;
3917     entry.rgExtension = &criticalExt;
3918     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3919      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3920     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3921     if (buf)
3922     {
3923         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3924         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3925         LocalFree(buf);
3926     }
3927     /* a CRL with an extension */
3928     entry.cExtension = 0;
3929     info.cExtension = 1;
3930     info.rgExtension = &criticalExt;
3931     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3932      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3933     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3934     if (buf)
3935     {
3936         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3937         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3938         LocalFree(buf);
3939     }
3940     /* a v2 CRL with an extension, this time non-critical */
3941     info.dwVersion = CRL_V2;
3942     info.rgExtension = &nonCriticalExt;
3943     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3944      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3945     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3946     if (buf)
3947     {
3948         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3949         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3950         LocalFree(buf);
3951     }
3952     /* a v2 CRL with an issuing dist point extension */
3953     ext.pszObjId = oid_issuing_dist_point;
3954     ext.fCritical = TRUE;
3955     ext.Value.cbData = sizeof(urlIDP);
3956     ext.Value.pbData = (LPBYTE)urlIDP;
3957     entry.rgExtension = &ext;
3958     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3959      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3960     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3961     if (buf)
3962     {
3963         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3964         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3965         LocalFree(buf);
3966     }
3967 }
3968
3969 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3970  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3971  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3972  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3973  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3974  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3975  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3976  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3977  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3978  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3979  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3980  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3981  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3982  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3983  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3984  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3985  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3986  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3987  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3988  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3989  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3990  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3991  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3992  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3993  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3994  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3995  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3996  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3997  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3998  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3999  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4000  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4001  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4002  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4003  0xcd };
4004 static const BYTE verisignCRLWithLotsOfEntries[] = {
4005 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4006 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4007 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4008 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4009 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4010 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4011 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4012 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4013 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4014 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4015 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4016 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4017 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4018 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4019 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4020 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4021 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4022 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4023 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4024 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4025 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4026 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4027 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4028 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4029 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4030 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4031 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4032 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4033 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4034 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4035 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4036 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4037 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4038 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4039 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4040 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4041 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4042 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4043 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4044 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4045 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4046 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4047 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4048 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4049 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4050 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4051 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4052 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4053 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4054 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4055 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4056 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4057 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4058 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4059 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4060 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4061 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4062 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4063 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4064 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4065 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4066 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4067 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4068 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4069 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4070 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4071 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4072 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4073 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4074 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4075 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4076 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4077 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4078 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4079 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4080 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4081 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4082 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4083 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4084 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4085 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4086 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4087 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4088 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4089 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4090 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4091 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4092 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4093 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4094 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4095 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4096 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4097 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4098 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4099 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4100 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4101 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4102 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4103 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4104 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4105 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4106 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4107 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4108 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4109 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4110 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4111 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4112 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4113 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4114 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4115 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4116 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4117 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4118 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4119 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4120 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4121 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4122 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4123 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4124 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4125 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4126 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4127 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4128 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4129 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4130 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4131 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4132 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4133 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4134 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4135 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4136 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4137 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4138 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4139 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4140 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4141 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4142 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4143 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4144 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4145 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4146 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4147 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4148 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4149 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4150 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4151 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4152 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4153 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4154 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4155 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4156 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4157 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4158 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4159 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4160 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4161 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4162 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4163 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4164 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4165 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4166 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4167 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4168 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4169 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4170 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4171 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4172 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4173 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4174 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4175 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4176 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4177 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4178 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4179 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4180 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4181 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4182 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4183 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4184 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4185 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4186 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4187 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4188 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4189 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4190 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4191 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4192 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4193 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4194 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4195 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4196 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4197 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4198 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4199 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4200 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4201 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4202 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4203 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4204 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4205 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4206 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4207 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4208 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4209 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4210 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4211 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4212 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4213 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4214 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4215 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4216 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4217 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4218 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4219 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4220 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4221 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4222 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4223 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4224 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4225 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4226 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4227 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4228 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4229 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4230 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4231 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4232 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4233 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4234 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4235 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4236 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4237 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4238 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4239 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4240 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4241 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4242 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4243 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4244 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4245 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4246 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4247 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4248 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4249 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4250 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4251 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4252 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4253 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4254 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4255 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4256 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4257 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4258 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4259 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4260 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4261 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4262 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4263 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4264 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4265 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4266 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4267 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4268 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4269 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4270 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4271 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4272 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4273 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4274 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4275 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4276 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4277 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4278 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4279 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4280 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4281 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4282 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4283 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4284 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4285 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4286 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4287 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4288 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4289 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4290 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4291 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4292 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4293 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4294 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4295 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4296 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4297 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4298 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4299 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4300 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4301 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4302 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4303 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4304 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4305 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4306 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4307 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4308 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4309 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4310 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4311 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4312 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4313 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4314 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4315 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4316 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4317 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4318 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4319 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4320 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4321 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4322 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4323 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4324 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4325 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4326 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4327 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4328 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4329 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4330 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4331 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4332 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4333 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4334 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4335 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4336 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4337 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4338 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4339 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4340 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4341 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4342 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4343 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4344 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4345 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4346 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4347 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4348 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4349 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4350 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4351 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4352 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4353 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4354 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4355 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4356 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4357 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4358 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4359 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4360 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4361 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4362 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4363 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4364 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4365 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4366 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4367 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4368 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4369 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4370 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4371 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4372 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4373 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4374 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4375 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4376 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4377 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4378 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4379 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4380 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4381 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4382 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4383 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4384 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4385 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4386 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4387 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4388 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4389 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4390 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4391 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4392 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4393 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4394 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4395 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4396 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4397 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4398 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4399 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4400 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4401 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4402 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4403 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4404 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4405 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4406 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4407 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4408 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4409 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4410 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4411 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4412 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4413 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4414 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4415 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4416 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4417 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4418 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4419 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4420 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4421 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4422 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4423 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4424 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4425 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4426 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4427 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4428 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4429 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4430 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4431 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4432 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4433 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4434 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4435 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4436 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4437 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4438 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4439 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4440 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4441 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4442 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4443 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4444 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4445 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4446 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4447 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4448 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4449 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4450 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4451 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4452 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4453 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4454 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4455 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4456 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4457 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4458 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4459 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4460 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4461 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4462 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4463 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4464 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4465 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4466 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4467 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4468 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4469 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4470 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4471 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4472 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4473 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4474 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4475 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4476 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4477 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4478 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4479 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4480 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4481 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4482 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4483 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4484 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4485 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4486 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4487 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4488 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4489 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4490 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4491 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4492 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4493 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4494 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4495 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4496 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4497 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4498 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4499 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4500 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4501 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4502 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4503 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4504 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4505 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4506 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4507 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4508 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4509 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4510 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4511 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4512 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4513
4514 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4515 {
4516     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4517     BOOL ret;
4518     BYTE *buf = NULL;
4519     DWORD size = 0, i;
4520
4521     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4522     {
4523         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4524          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4525          &buf, &size);
4526         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4527          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4528          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4529          GetLastError());
4530     }
4531     /* at a minimum, a CRL must contain an issuer: */
4532     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4533      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4534      &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), "Wrong size %d\n", size);
4541         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4542          info->cCRLEntry);
4543         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4544          "Wrong issuer size %d\n", info->Issuer.cbData);
4545         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4546          "Unexpected issuer\n");
4547         LocalFree(buf);
4548     }
4549     /* check decoding with an empty CRL entry */
4550     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4551      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4552      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4553     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4554      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4555      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4556      GetLastError());
4557     /* with a real CRL entry */
4558     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4559      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4560      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4561     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4562     if (buf)
4563     {
4564         CRL_INFO *info = (CRL_INFO *)buf;
4565         CRL_ENTRY *entry;
4566
4567         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4568         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4569          info->cCRLEntry);
4570         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4571         entry = info->rgCRLEntry;
4572         ok(entry->SerialNumber.cbData == 1,
4573          "Expected serial number size 1, got %d\n",
4574          entry->SerialNumber.cbData);
4575         ok(*entry->SerialNumber.pbData == *serialNum,
4576          "Expected serial number %d, got %d\n", *serialNum,
4577          *entry->SerialNumber.pbData);
4578         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4579          "Wrong issuer size %d\n", info->Issuer.cbData);
4580         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4581          "Unexpected issuer\n");
4582         LocalFree(buf);
4583     }
4584     /* a real CRL from verisign that has extensions */
4585     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4586      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4587      NULL, &buf, &size);
4588     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4589     if (buf)
4590     {
4591         CRL_INFO *info = (CRL_INFO *)buf;
4592         CRL_ENTRY *entry;
4593
4594         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4595         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4596          info->cCRLEntry);
4597         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4598         entry = info->rgCRLEntry;
4599         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4600          info->cExtension);
4601         LocalFree(buf);
4602     }
4603     /* another real CRL from verisign that has lots of entries */
4604     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4605      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4606      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4607     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4608     if (buf)
4609     {
4610         CRL_INFO *info = (CRL_INFO *)buf;
4611
4612         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4613         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4614          info->cCRLEntry);
4615         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4616          info->cExtension);
4617         LocalFree(buf);
4618     }
4619     /* and finally, with an extension */
4620     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4621      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4622      NULL, &buf, &size);
4623     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4624     if (buf)
4625     {
4626         CRL_INFO *info = (CRL_INFO *)buf;
4627         CRL_ENTRY *entry;
4628
4629         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4630         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4631          info->cCRLEntry);
4632         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4633         entry = info->rgCRLEntry;
4634         ok(entry->SerialNumber.cbData == 1,
4635          "Expected serial number size 1, got %d\n",
4636          entry->SerialNumber.cbData);
4637         ok(*entry->SerialNumber.pbData == *serialNum,
4638          "Expected serial number %d, got %d\n", *serialNum,
4639          *entry->SerialNumber.pbData);
4640         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4641          "Wrong issuer size %d\n", info->Issuer.cbData);
4642         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4643          "Unexpected issuer\n");
4644         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4645          info->cExtension);
4646         LocalFree(buf);
4647     }
4648     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4649      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4650      NULL, &buf, &size);
4651     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4652     if (buf)
4653     {
4654         CRL_INFO *info = (CRL_INFO *)buf;
4655
4656         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4657          info->cExtension);
4658         LocalFree(buf);
4659     }
4660     /* And again, with an issuing dist point */
4661     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4662      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4663      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4664     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4665     if (buf)
4666     {
4667         CRL_INFO *info = (CRL_INFO *)buf;
4668
4669         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4670          info->cExtension);
4671         LocalFree(buf);
4672     }
4673 }
4674
4675 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4676  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4677 static const BYTE encodedUsage[] = {
4678  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4679  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4680  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4681
4682 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4683 {
4684     BOOL ret;
4685     BYTE *buf = NULL;
4686     DWORD size = 0;
4687     CERT_ENHKEY_USAGE usage;
4688
4689     /* Test with empty usage */
4690     usage.cUsageIdentifier = 0;
4691     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4692      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4693     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4694     if (buf)
4695     {
4696         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4697         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4698         LocalFree(buf);
4699     }
4700     /* Test with a few usages */
4701     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4702     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4703     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4704      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4705     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4706     if (buf)
4707     {
4708         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4709         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4710         LocalFree(buf);
4711     }
4712 }
4713
4714 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4715 {
4716     BOOL ret;
4717     LPBYTE buf = NULL;
4718     DWORD size = 0;
4719
4720     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4721      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4722      &buf, &size);
4723     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4724     if (buf)
4725     {
4726         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4727
4728         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4729          "Wrong size %d\n", size);
4730         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4731          usage->cUsageIdentifier);
4732         LocalFree(buf);
4733     }
4734     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4735      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4736      &buf, &size);
4737     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4738     if (buf)
4739     {
4740         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4741         DWORD i;
4742
4743         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4744          "Wrong size %d\n", size);
4745         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4746          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4747         for (i = 0; i < usage->cUsageIdentifier; i++)
4748             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4749              "Expected OID %s, got %s\n", keyUsages[i],
4750              usage->rgpszUsageIdentifier[i]);
4751         LocalFree(buf);
4752     }
4753 }
4754
4755 static BYTE keyId[] = { 1,2,3,4 };
4756 static const BYTE authorityKeyIdWithId[] = {
4757  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4758 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4759  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4760  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4761 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4762
4763 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4764 {
4765     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4766     BOOL ret;
4767     BYTE *buf = NULL;
4768     DWORD size = 0;
4769
4770     /* Test with empty id */
4771     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4772      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4773     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4774     if (buf)
4775     {
4776         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4777         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4778         LocalFree(buf);
4779     }
4780     /* With just a key id */
4781     info.KeyId.cbData = sizeof(keyId);
4782     info.KeyId.pbData = keyId;
4783     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4784      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4785     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4786     if (buf)
4787     {
4788         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4789         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4790         LocalFree(buf);
4791     }
4792     /* With just an issuer */
4793     info.KeyId.cbData = 0;
4794     info.CertIssuer.cbData = sizeof(encodedCommonName);
4795     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4796     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4797      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4798     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4799     if (buf)
4800     {
4801         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4802          size);
4803         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4804         LocalFree(buf);
4805     }
4806     /* With just a serial number */
4807     info.CertIssuer.cbData = 0;
4808     info.CertSerialNumber.cbData = sizeof(serialNum);
4809     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4810     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4811      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4812     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4813     if (buf)
4814     {
4815         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4816          size);
4817         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4818         LocalFree(buf);
4819     }
4820 }
4821
4822 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4823 {
4824     BOOL ret;
4825     LPBYTE buf = NULL;
4826     DWORD size = 0;
4827
4828     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4829      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4830      &buf, &size);
4831     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4832     if (buf)
4833     {
4834         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4835
4836         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4837          size);
4838         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4839         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4840         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4841         LocalFree(buf);
4842     }
4843     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4844      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4845      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4846     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4847     if (buf)
4848     {
4849         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4850
4851         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4852          size);
4853         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4854         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4855          "Unexpected key id\n");
4856         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4857         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4858         LocalFree(buf);
4859     }
4860     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4861      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4862      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4863     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4864     if (buf)
4865     {
4866         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4867
4868         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4869          size);
4870         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4871         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4872          "Unexpected issuer len\n");
4873         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4874          sizeof(encodedCommonName)), "Unexpected issuer\n");
4875         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4876         LocalFree(buf);
4877     }
4878     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4879      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4880      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4881     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4882     if (buf)
4883     {
4884         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4885
4886         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4887          size);
4888         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4889         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4890         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4891          "Unexpected serial number len\n");
4892         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4893          "Unexpected serial number\n");
4894         LocalFree(buf);
4895     }
4896 }
4897
4898 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4899  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4900  0x6f,0x72,0x67 };
4901
4902 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4903 {
4904     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4905     CERT_ALT_NAME_ENTRY entry = { 0 };
4906     BOOL ret;
4907     BYTE *buf = NULL;
4908     DWORD size = 0;
4909
4910     /* Test with empty id */
4911     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4912      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4913     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4914     if (buf)
4915     {
4916         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4917         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4918         LocalFree(buf);
4919     }
4920     /* With just a key id */
4921     info.KeyId.cbData = sizeof(keyId);
4922     info.KeyId.pbData = keyId;
4923     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4924      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4925     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4926     if (buf)
4927     {
4928         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4929          size);
4930         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4931         LocalFree(buf);
4932     }
4933     /* With a bogus issuer name */
4934     info.KeyId.cbData = 0;
4935     info.AuthorityCertIssuer.cAltEntry = 1;
4936     info.AuthorityCertIssuer.rgAltEntry = &entry;
4937     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4938      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4939     ok(!ret && GetLastError() == E_INVALIDARG,
4940      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4941     /* With an issuer name */
4942     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4943     U(entry).pwszURL = (LPWSTR)url;
4944     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4945      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4946     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4947     if (buf)
4948     {
4949         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4950          size);
4951         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4952          "Unexpected value\n");
4953         LocalFree(buf);
4954     }
4955     /* With just a serial number */
4956     info.AuthorityCertIssuer.cAltEntry = 0;
4957     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4958     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4959     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4960      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4961     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4962     if (buf)
4963     {
4964         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4965          size);
4966         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4967         LocalFree(buf);
4968     }
4969 }
4970
4971 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4972 {
4973     BOOL ret;
4974     LPBYTE buf = NULL;
4975     DWORD size = 0;
4976
4977     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4978      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4979      &buf, &size);
4980     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4981     if (buf)
4982     {
4983         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4984
4985         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4986          size);
4987         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4988         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4989          "Expected no issuer name entries\n");
4990         ok(info->AuthorityCertSerialNumber.cbData == 0,
4991          "Expected no serial number\n");
4992         LocalFree(buf);
4993     }
4994     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4995      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4996      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4997     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4998     if (buf)
4999     {
5000         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5001
5002         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5003          size);
5004         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5005         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5006          "Unexpected key id\n");
5007         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5008          "Expected no issuer name entries\n");
5009         ok(info->AuthorityCertSerialNumber.cbData == 0,
5010          "Expected no serial number\n");
5011         LocalFree(buf);
5012     }
5013     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5014      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5015      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5016     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5017     if (buf)
5018     {
5019         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5020
5021         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5022          size);
5023         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5024         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5025          "Expected 1 issuer entry, got %d\n",
5026          info->AuthorityCertIssuer.cAltEntry);
5027         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5028          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5029          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5030         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5031          url), "Unexpected URL\n");
5032         ok(info->AuthorityCertSerialNumber.cbData == 0,
5033          "Expected no serial number\n");
5034         LocalFree(buf);
5035     }
5036     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5037      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5038      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5039     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5040     if (buf)
5041     {
5042         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5043
5044         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5045          size);
5046         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5047         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5048          "Expected no issuer name entries\n");
5049         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5050          "Unexpected serial number len\n");
5051         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5052          sizeof(serialNum)), "Unexpected serial number\n");
5053         LocalFree(buf);
5054     }
5055 }
5056
5057 static const BYTE authorityInfoAccessWithUrl[] = {
5058 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5059 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5060 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5061 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5062 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5063 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5064
5065 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5066 {
5067     static char oid1[] = "1.2.3";
5068     static char oid2[] = "1.5.6";
5069     BOOL ret;
5070     BYTE *buf = NULL;
5071     DWORD size = 0;
5072     CERT_ACCESS_DESCRIPTION accessDescription[2];
5073     CERT_AUTHORITY_INFO_ACCESS aia;
5074
5075     memset(accessDescription, 0, sizeof(accessDescription));
5076     aia.cAccDescr = 0;
5077     aia.rgAccDescr = NULL;
5078     /* Having no access descriptions is allowed */
5079     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5080      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5081     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5082     if (buf)
5083     {
5084         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5085         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5086         LocalFree(buf);
5087         buf = NULL;
5088     }
5089     /* It can't have an empty access method */
5090     aia.cAccDescr = 1;
5091     aia.rgAccDescr = accessDescription;
5092     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5093      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5094     ok(!ret && (GetLastError() == E_INVALIDARG ||
5095      GetLastError() == OSS_LIMITED /* Win9x */),
5096      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5097     /* It can't have an empty location */
5098     accessDescription[0].pszAccessMethod = oid1;
5099     SetLastError(0xdeadbeef);
5100     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5101      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5102     ok(!ret && GetLastError() == E_INVALIDARG,
5103      "expected E_INVALIDARG, got %08x\n", GetLastError());
5104     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5105     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5106     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5107      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5108     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5109     if (buf)
5110     {
5111         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5112          size);
5113         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5114          "unexpected value\n");
5115         LocalFree(buf);
5116         buf = NULL;
5117     }
5118     accessDescription[1].pszAccessMethod = oid2;
5119     accessDescription[1].AccessLocation.dwAltNameChoice =
5120      CERT_ALT_NAME_IP_ADDRESS;
5121     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5122      sizeof(encodedIPAddr);
5123     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5124      (LPBYTE)encodedIPAddr;
5125     aia.cAccDescr = 2;
5126     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5127      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5128     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5129     if (buf)
5130     {
5131         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5132          "unexpected size %d\n", size);
5133         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5134          "unexpected value\n");
5135         LocalFree(buf);
5136         buf = NULL;
5137     }
5138 }
5139
5140 static void compareAuthorityInfoAccess(LPCSTR header,
5141  const CERT_AUTHORITY_INFO_ACCESS *expected,
5142  const CERT_AUTHORITY_INFO_ACCESS *got)
5143 {
5144     DWORD i;
5145
5146     ok(expected->cAccDescr == got->cAccDescr,
5147      "%s: expected %d access descriptions, got %d\n", header,
5148      expected->cAccDescr, got->cAccDescr);
5149     for (i = 0; i < expected->cAccDescr; i++)
5150     {
5151         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5152          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5153          header, i, expected->rgAccDescr[i].pszAccessMethod,
5154          got->rgAccDescr[i].pszAccessMethod);
5155         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5156          &got->rgAccDescr[i].AccessLocation);
5157     }
5158 }
5159
5160 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5161 {
5162     static char oid1[] = "1.2.3";
5163     static char oid2[] = "1.5.6";
5164     BOOL ret;
5165     LPBYTE buf = NULL;
5166     DWORD size = 0;
5167
5168     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5169      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5170      &buf, &size);
5171     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5172     if (buf)
5173     {
5174         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5175
5176         compareAuthorityInfoAccess("empty AIA", &aia,
5177          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5178         LocalFree(buf);
5179         buf = NULL;
5180     }
5181     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5182      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5183      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5184     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5185     if (buf)
5186     {
5187         CERT_ACCESS_DESCRIPTION accessDescription;
5188         CERT_AUTHORITY_INFO_ACCESS aia;
5189
5190         accessDescription.pszAccessMethod = oid1;
5191         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5192         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5193         aia.cAccDescr = 1;
5194         aia.rgAccDescr = &accessDescription;
5195         compareAuthorityInfoAccess("AIA with URL", &aia,
5196          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5197         LocalFree(buf);
5198         buf = NULL;
5199     }
5200     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5201      authorityInfoAccessWithUrlAndIPAddr,
5202      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5203      NULL, &buf, &size);
5204     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5205     if (buf)
5206     {
5207         CERT_ACCESS_DESCRIPTION accessDescription[2];
5208         CERT_AUTHORITY_INFO_ACCESS aia;
5209
5210         accessDescription[0].pszAccessMethod = oid1;
5211         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5212         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5213         accessDescription[1].pszAccessMethod = oid2;
5214         accessDescription[1].AccessLocation.dwAltNameChoice =
5215          CERT_ALT_NAME_IP_ADDRESS;
5216         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5217          sizeof(encodedIPAddr);
5218         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5219          (LPBYTE)encodedIPAddr;
5220         aia.cAccDescr = 2;
5221         aia.rgAccDescr = accessDescription;
5222         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5223          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5224         LocalFree(buf);
5225         buf = NULL;
5226     }
5227 }
5228
5229 static const BYTE emptyCTL[] = {
5230 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5231 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5232 static const BYTE emptyCTLWithVersion1[] = {
5233 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5234 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5235 static const BYTE ctlWithUsageIdentifier[] = {
5236 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5237 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5238 static const BYTE ctlWithListIdentifier[] = {
5239 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5240 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5241 static const BYTE ctlWithSequenceNumber[] = {
5242 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5243 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5244 static const BYTE ctlWithThisUpdate[] = {
5245 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5246 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5247 static const BYTE ctlWithThisAndNextUpdate[] = {
5248 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5249 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5250 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5251 static const BYTE ctlWithAlgId[] = {
5252 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5253 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5254 static const BYTE ctlWithBogusEntry[] = {
5255 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5256 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5257 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5258 static const BYTE ctlWithOneEntry[] = {
5259 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5260 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5261 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5262 static const BYTE ctlWithTwoEntries[] = {
5263 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5264 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5265 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5266 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5267 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5268
5269 static void test_encodeCTL(DWORD dwEncoding)
5270 {
5271     static char oid1[] = "1.2.3";
5272     static char oid2[] = "1.5.6";
5273     char *pOid1 = oid1;
5274     BOOL ret;
5275     BYTE *buf = NULL;
5276     DWORD size = 0;
5277     CTL_INFO info;
5278     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5279     CTL_ENTRY ctlEntry[2];
5280     CRYPT_ATTRIBUTE attr1, attr2;
5281     CRYPT_ATTR_BLOB value1, value2;
5282
5283     memset(&info, 0, sizeof(info));
5284     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5285      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5286     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5287     if (buf)
5288     {
5289         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5290         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5291         LocalFree(buf);
5292         buf = NULL;
5293     }
5294     info.dwVersion = 1;
5295     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5296      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5297     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5298     if (buf)
5299     {
5300         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5301         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5302         LocalFree(buf);
5303         buf = NULL;
5304     }
5305     info.dwVersion = 0;
5306     info.SubjectUsage.cUsageIdentifier = 1;
5307     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5308     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5309      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5310     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5311     if (buf)
5312     {
5313         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5314          size);
5315         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5316         LocalFree(buf);
5317         buf = NULL;
5318     }
5319     info.SubjectUsage.cUsageIdentifier = 0;
5320     info.ListIdentifier.cbData = sizeof(serialNum);
5321     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5322     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5323      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5324     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5325     if (buf)
5326     {
5327         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5328         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5329         LocalFree(buf);
5330         buf = NULL;
5331     }
5332     info.ListIdentifier.cbData = 0;
5333     info.SequenceNumber.cbData = sizeof(serialNum);
5334     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5335     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5336      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5337     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5338     if (buf)
5339     {
5340         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5341          size);
5342         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5343         LocalFree(buf);
5344         buf = NULL;
5345     }
5346     info.SequenceNumber.cbData = 0;
5347     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5348     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5349      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5350     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5351     if (buf)
5352     {
5353         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5354         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5355         LocalFree(buf);
5356         buf = NULL;
5357     }
5358     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5359     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5360      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5361     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5362     if (buf)
5363     {
5364         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5365          size);
5366         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5367         LocalFree(buf);
5368         buf = NULL;
5369     }
5370     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5371     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5372     info.SubjectAlgorithm.pszObjId = oid2;
5373     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5374      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5375     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5376     if (buf)
5377     {
5378         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5379         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5380         LocalFree(buf);
5381         buf = NULL;
5382     }
5383     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5384      * (see tests below) but it'll encode fine.
5385      */
5386     info.SubjectAlgorithm.pszObjId = NULL;
5387     value1.cbData = sizeof(serialNum);
5388     value1.pbData = (LPBYTE)serialNum;
5389     attr1.pszObjId = oid1;
5390     attr1.cValue = 1;
5391     attr1.rgValue = &value1;
5392     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5393     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5394     ctlEntry[0].cAttribute = 1;
5395     ctlEntry[0].rgAttribute = &attr1;
5396     info.cCTLEntry = 1;
5397     info.rgCTLEntry = ctlEntry;
5398     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5400     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5401     if (buf)
5402     {
5403         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5404         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5405         LocalFree(buf);
5406         buf = NULL;
5407     }
5408     value1.cbData = sizeof(emptySequence);
5409     value1.pbData = (LPBYTE)emptySequence;
5410     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5411      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5412     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5413     if (buf)
5414     {
5415         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5416         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5417         LocalFree(buf);
5418         buf = NULL;
5419     }
5420     value2.cbData = sizeof(encodedIPAddr);
5421     value2.pbData = (LPBYTE)encodedIPAddr;
5422     attr2.pszObjId = oid2;
5423     attr2.cValue = 1;
5424     attr2.rgValue = &value2;
5425     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5426     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5427     ctlEntry[1].cAttribute = 1;
5428     ctlEntry[1].rgAttribute = &attr2;
5429     info.cCTLEntry = 2;
5430     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5431      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5432     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5433     if (buf)
5434     {
5435         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5436         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5437         LocalFree(buf);
5438         buf = NULL;
5439     }
5440 }
5441
5442 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5443  const CTL_INFO *got)
5444 {
5445     DWORD i, j, k;
5446
5447     ok(expected->dwVersion == got->dwVersion,
5448      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5449      got->dwVersion);
5450     ok(expected->SubjectUsage.cUsageIdentifier ==
5451      got->SubjectUsage.cUsageIdentifier,
5452      "%s: expected %d usage identifiers, got %d\n", header,
5453      expected->SubjectUsage.cUsageIdentifier,
5454      got->SubjectUsage.cUsageIdentifier);
5455     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5456         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5457          got->SubjectUsage.rgpszUsageIdentifier[i]),
5458          "%s[%d]: expected %s, got %s\n", header, i,
5459          expected->SubjectUsage.rgpszUsageIdentifier[i],
5460          got->SubjectUsage.rgpszUsageIdentifier[i]);
5461     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5462      "%s: expected list identifier of %d bytes, got %d\n", header,
5463      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5464     if (expected->ListIdentifier.cbData)
5465         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5466          expected->ListIdentifier.cbData),
5467          "%s: unexpected list identifier value\n", header);
5468     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5469      "%s: expected sequence number of %d bytes, got %d\n", header,
5470      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5471     if (expected->SequenceNumber.cbData)
5472         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5473          expected->SequenceNumber.cbData),
5474          "%s: unexpected sequence number value\n", header);
5475     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5476      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5477      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5478      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5479     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5480      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5481      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5482      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5483     if (expected->SubjectAlgorithm.pszObjId &&
5484      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5485         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5486          expected->SubjectAlgorithm.pszObjId);
5487     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5488         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5489          got->SubjectAlgorithm.pszObjId),
5490          "%s: expected subject algorithm %s, got %s\n", header,
5491          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5492     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5493      got->SubjectAlgorithm.Parameters.cbData,
5494      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5495      expected->SubjectAlgorithm.Parameters.cbData,
5496      got->SubjectAlgorithm.Parameters.cbData);
5497     if (expected->SubjectAlgorithm.Parameters.cbData)
5498         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5499          got->SubjectAlgorithm.Parameters.pbData,
5500          expected->SubjectAlgorithm.Parameters.cbData),
5501          "%s: unexpected subject algorithm parameter value\n", header);
5502     ok(expected->cCTLEntry == got->cCTLEntry,
5503      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5504      got->cCTLEntry);
5505     for (i = 0; i < expected->cCTLEntry; i++)
5506     {
5507         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5508          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5509          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5510          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5511          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5512         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5513             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5514              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5515              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5516              "%s[%d]: unexpected subject identifier value\n",
5517              header, i);
5518         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5519         {
5520             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5521              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5522              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5523              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5524              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5525             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5526             {
5527                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5528                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5529                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5530                  header, i, j, k,
5531                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5532                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5533                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5534                     ok(!memcmp(
5535                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5536                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5537                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5538                      "%s[%d][%d][%d]: unexpected value\n",
5539                      header, i, j, k);
5540             }
5541         }
5542     }
5543     ok(expected->cExtension == got->cExtension,
5544      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5545      got->cExtension);
5546     for (i = 0; i < expected->cExtension; i++)
5547     {
5548         ok(!strcmp(expected->rgExtension[i].pszObjId,
5549          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5550          header, i, expected->rgExtension[i].pszObjId,
5551          got->rgExtension[i].pszObjId);
5552         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5553          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5554          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5555         ok(expected->rgExtension[i].Value.cbData ==
5556          got->rgExtension[i].Value.cbData,
5557          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5558          header, i, expected->rgExtension[i].Value.cbData,
5559          got->rgExtension[i].Value.cbData);
5560         if (expected->rgExtension[i].Value.cbData)
5561             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5562              got->rgExtension[i].Value.pbData,
5563              expected->rgExtension[i].Value.cbData),
5564              "%s[%d]: unexpected extension value\n", header, i);
5565     }
5566 }
5567
5568 static const BYTE signedCTL[] = {
5569 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5570 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5571 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5572 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5573 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5574 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5575 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5576 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5577 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5578 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5579 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5580 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5581 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5582 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5583 static const BYTE signedCTLWithCTLInnerContent[] = {
5584 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5585 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5586 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5587 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5588 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5589 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5590 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5591 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5592 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5593 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5594 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5595 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5596 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5597 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5598 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5599 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5600 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5601 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5602 0x57,0x6c,0x0b,0x47,0xb8 };
5603
5604 static void test_decodeCTL(DWORD dwEncoding)
5605 {
5606     static char oid1[] = "1.2.3";
5607     static char oid2[] = "1.5.6";
5608     static BYTE nullData[] = { 5,0 };
5609     char *pOid1 = oid1;
5610     BOOL ret;
5611     BYTE *buf = NULL;
5612     DWORD size = 0;
5613     CTL_INFO info;
5614     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5615     CTL_ENTRY ctlEntry[2];
5616     CRYPT_ATTRIBUTE attr1, attr2;
5617     CRYPT_ATTR_BLOB value1, value2;
5618
5619     memset(&info, 0, sizeof(info));
5620     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5621      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5622     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5623     if (buf)
5624     {
5625         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5626         LocalFree(buf);
5627         buf = NULL;
5628     }
5629     info.dwVersion = 1;
5630     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5631      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5632      &size);
5633     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5634     if (buf)
5635     {
5636         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5637         LocalFree(buf);
5638         buf = NULL;
5639     }
5640     info.dwVersion = 0;
5641     info.SubjectUsage.cUsageIdentifier = 1;
5642     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5643     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5644      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5645      &buf, &size);
5646     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5647     if (buf)
5648     {
5649         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5650         LocalFree(buf);
5651         buf = NULL;
5652     }
5653     info.SubjectUsage.cUsageIdentifier = 0;
5654     info.ListIdentifier.cbData = sizeof(serialNum);
5655     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5656     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5657      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5658     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5659     if (buf)
5660     {
5661         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5662         LocalFree(buf);
5663         buf = NULL;
5664     }
5665     info.ListIdentifier.cbData = 0;
5666     info.SequenceNumber.cbData = sizeof(serialNum);
5667     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5668     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5669      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5670     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5671     if (buf)
5672     {
5673         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5674         LocalFree(buf);
5675         buf = NULL;
5676     }
5677     info.SequenceNumber.cbData = 0;
5678     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5679     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5680      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5681     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5682     if (buf)
5683     {
5684         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5685         LocalFree(buf);
5686         buf = NULL;
5687     }
5688     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5689     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5690      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5691      &buf, &size);
5692     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5693     if (buf)
5694     {
5695         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5696         LocalFree(buf);
5697         buf = NULL;
5698     }
5699     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5700     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5701     info.SubjectAlgorithm.pszObjId = oid2;
5702     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5703     info.SubjectAlgorithm.Parameters.pbData = nullData;
5704     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5705      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5706     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5707     if (buf)
5708     {
5709         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5710         LocalFree(buf);
5711         buf = NULL;
5712     }
5713     SetLastError(0xdeadbeef);
5714     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5715      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5716     ok(!ret &&
5717      (GetLastError() == CRYPT_E_ASN1_EOD ||
5718       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5719       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5720      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5721      GetLastError());
5722     info.SubjectAlgorithm.Parameters.cbData = 0;
5723     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5724     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5725     info.SubjectAlgorithm.pszObjId = oid2;
5726     info.SubjectAlgorithm.pszObjId = NULL;
5727     value1.cbData = sizeof(emptySequence);
5728     value1.pbData = (LPBYTE)emptySequence;
5729     attr1.pszObjId = oid1;
5730     attr1.cValue = 1;
5731     attr1.rgValue = &value1;
5732     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5733     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5734     ctlEntry[0].cAttribute = 1;
5735     ctlEntry[0].rgAttribute = &attr1;
5736     info.cCTLEntry = 1;
5737     info.rgCTLEntry = ctlEntry;
5738     SetLastError(0xdeadbeef);
5739     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5740      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5741     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5742     if (buf)
5743     {
5744         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5745         LocalFree(buf);
5746         buf = NULL;
5747     }
5748     value2.cbData = sizeof(encodedIPAddr);
5749     value2.pbData = (LPBYTE)encodedIPAddr;
5750     attr2.pszObjId = oid2;
5751     attr2.cValue = 1;
5752     attr2.rgValue = &value2;
5753     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5754     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5755     ctlEntry[1].cAttribute = 1;
5756     ctlEntry[1].rgAttribute = &attr2;
5757     info.cCTLEntry = 2;
5758     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5759      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5760     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5761     if (buf)
5762     {
5763         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5764         LocalFree(buf);
5765         buf = NULL;
5766     }
5767     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5768     SetLastError(0xdeadbeef);
5769     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5770      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5771     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5772      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5773      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5774      GetLastError());
5775     SetLastError(0xdeadbeef);
5776     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5777      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5778      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5779     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5780      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5781      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5782      GetLastError());
5783 }
5784
5785 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5786 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5787  0x03,0,0,0,0,0,0 };
5788 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5789  0xa0,0x01,0x01 };
5790 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5791  0x03,0x02,0x01,0x01 };
5792 static BYTE bogusDER[] = { 1 };
5793
5794 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5795 {
5796     BOOL ret;
5797     BYTE *buf = NULL;
5798     DWORD size = 0;
5799     CRYPT_CONTENT_INFO info = { 0 };
5800     char oid1[] = "1.2.3";
5801
5802     if (0)
5803     {
5804         /* Crashes on win9x */
5805         SetLastError(0xdeadbeef);
5806         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5807          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5808         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5809          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5810     }
5811     SetLastError(0xdeadbeef);
5812     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5813      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5814     ok(!ret && (GetLastError() == E_INVALIDARG ||
5815      GetLastError() == OSS_LIMITED /* Win9x */),
5816      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5817     info.pszObjId = oid1;
5818     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5819      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5820     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5821     if (buf)
5822     {
5823         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5824         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5825         LocalFree(buf);
5826     }
5827     info.Content.pbData = bogusDER;
5828     info.Content.cbData = sizeof(bogusDER);
5829     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5830      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5831     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5832     if (buf)
5833     {
5834         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5835         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5836         LocalFree(buf);
5837     }
5838     info.Content.pbData = (BYTE *)ints[0].encoded;
5839     info.Content.cbData = ints[0].encoded[1] + 2;
5840     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5841      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5842     if (buf)
5843     {
5844         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5845         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5846         LocalFree(buf);
5847     }
5848 }
5849
5850 static const BYTE indefiniteSignedPKCSContent[] = {
5851 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5852 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5853 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5854 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5855 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5856 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5857 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5858 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5859 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5860 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5861 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5862 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5863 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5864 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5865 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5866 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5867 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5868 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5869 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5870 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5871 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5872 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5873 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5874 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5875 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5876 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5877 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5878 0x00,0x00,0x00,0x00,0x00,0x00 };
5879
5880 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5881 {
5882     BOOL ret;
5883     LPBYTE buf = NULL;
5884     DWORD size = 0;
5885     CRYPT_CONTENT_INFO *info;
5886
5887     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5888      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5889      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5890     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5891     if (buf)
5892     {
5893         info = (CRYPT_CONTENT_INFO *)buf;
5894
5895         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5896          info->pszObjId);
5897         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5898          info->Content.cbData);
5899         LocalFree(buf);
5900     }
5901     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5902      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5903      0, NULL, NULL, &size);
5904     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5905     SetLastError(0xdeadbeef);
5906     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5907      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5908      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5909     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5910      * I doubt an app depends on that.
5911      */
5912     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5913      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5914      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5915      GetLastError());
5916     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5917      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5918      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5919     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5920     if (buf)
5921     {
5922         info = (CRYPT_CONTENT_INFO *)buf;
5923
5924         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5925          info->pszObjId);
5926         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5927          "Unexpected size %d\n", info->Content.cbData);
5928         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5929          info->Content.cbData), "Unexpected value\n");
5930         LocalFree(buf);
5931     }
5932     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5933      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5934      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5935     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5936     if (buf)
5937     {
5938         info = (CRYPT_CONTENT_INFO *)buf;
5939
5940         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5941          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5942         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5943          info->Content.cbData);
5944         LocalFree(buf);
5945     }
5946 }
5947
5948 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5949  0x00 };
5950 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5951  0x01 };
5952 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5953  0x02,0x01,0x01 };
5954
5955 static void test_encodePKCSAttribute(DWORD dwEncoding)
5956 {
5957     CRYPT_ATTRIBUTE attr = { 0 };
5958     BOOL ret;
5959     LPBYTE buf = NULL;
5960     DWORD size = 0;
5961     CRYPT_ATTR_BLOB blob;
5962     char oid[] = "1.2.3";
5963
5964     if (0)
5965     {
5966         /* Crashes on win9x */
5967         SetLastError(0xdeadbeef);
5968         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5969          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5970         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5971          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5972     }
5973     SetLastError(0xdeadbeef);
5974     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5975      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5976     ok(!ret && (GetLastError() == E_INVALIDARG ||
5977      GetLastError() == OSS_LIMITED /* Win9x */),
5978      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5979     attr.pszObjId = oid;
5980     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5981      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5982     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5983     if (buf)
5984     {
5985         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5986         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5987         LocalFree(buf);
5988     }
5989     blob.cbData = sizeof(bogusDER);
5990     blob.pbData = bogusDER;
5991     attr.cValue = 1;
5992     attr.rgValue = &blob;
5993     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5994      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5995     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5996     if (buf)
5997     {
5998         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5999         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6000         LocalFree(buf);
6001     }
6002     blob.pbData = (BYTE *)ints[0].encoded;
6003     blob.cbData = ints[0].encoded[1] + 2;
6004     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6005      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6006     if (buf)
6007     {
6008         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6009         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6010         LocalFree(buf);
6011     }
6012 }
6013
6014 static void test_decodePKCSAttribute(DWORD dwEncoding)
6015 {
6016     BOOL ret;
6017     LPBYTE buf = NULL;
6018     DWORD size = 0;
6019     CRYPT_ATTRIBUTE *attr;
6020
6021     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6022      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6023      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6024     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6025     if (buf)
6026     {
6027         attr = (CRYPT_ATTRIBUTE *)buf;
6028
6029         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6030          attr->pszObjId);
6031         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6032         LocalFree(buf);
6033     }
6034     SetLastError(0xdeadbeef);
6035     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6036      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6037      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6038     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6039      * I doubt an app depends on that.
6040      */
6041     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6042      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6043      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6044      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6045      GetLastError());
6046     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6047      intPKCSAttr, sizeof(intPKCSAttr),
6048      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6049     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6050     if (buf)
6051     {
6052         attr = (CRYPT_ATTRIBUTE *)buf;
6053
6054         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6055          attr->pszObjId);
6056         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6057         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6058          "Unexpected size %d\n", attr->rgValue[0].cbData);
6059         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6060          attr->rgValue[0].cbData), "Unexpected value\n");
6061         LocalFree(buf);
6062     }
6063 }
6064
6065 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6066 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6067  0x2a,0x03,0x31,0x00 };
6068 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6069  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6070
6071 static void test_encodePKCSAttributes(DWORD dwEncoding)
6072 {
6073     CRYPT_ATTRIBUTES attributes = { 0 };
6074     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6075     CRYPT_ATTR_BLOB blob;
6076     BOOL ret;
6077     LPBYTE buf = NULL;
6078     DWORD size = 0;
6079     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6080
6081     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6082      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6083     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6084     if (buf)
6085     {
6086         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6087         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6088         LocalFree(buf);
6089     }
6090     attributes.cAttr = 1;
6091     attributes.rgAttr = attr;
6092     SetLastError(0xdeadbeef);
6093     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6094      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6095     ok(!ret && (GetLastError() == E_INVALIDARG ||
6096      GetLastError() == OSS_LIMITED /* Win9x */),
6097      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6098     attr[0].pszObjId = oid1;
6099     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6100      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6101     if (buf)
6102     {
6103         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6104         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6105         LocalFree(buf);
6106     }
6107     attr[1].pszObjId = oid2;
6108     attr[1].cValue = 1;
6109     attr[1].rgValue = &blob;
6110     blob.pbData = (BYTE *)ints[0].encoded;
6111     blob.cbData = ints[0].encoded[1] + 2;
6112     attributes.cAttr = 2;
6113     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6114      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6115     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6116     if (buf)
6117     {
6118         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6119         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6120         LocalFree(buf);
6121     }
6122 }
6123
6124 static void test_decodePKCSAttributes(DWORD dwEncoding)
6125 {
6126     BOOL ret;
6127     LPBYTE buf = NULL;
6128     DWORD size = 0;
6129     CRYPT_ATTRIBUTES *attributes;
6130
6131     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6132      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6133      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6134     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6135     if (buf)
6136     {
6137         attributes = (CRYPT_ATTRIBUTES *)buf;
6138         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6139          attributes->cAttr);
6140         LocalFree(buf);
6141     }
6142     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6143      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6144      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6145     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6146     if (buf)
6147     {
6148         attributes = (CRYPT_ATTRIBUTES *)buf;
6149         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6150          attributes->cAttr);
6151         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6152          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6153         ok(attributes->rgAttr[0].cValue == 0,
6154          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6155         LocalFree(buf);
6156     }
6157     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6158      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6159      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6160     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6161     if (buf)
6162     {
6163         attributes = (CRYPT_ATTRIBUTES *)buf;
6164         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6165          attributes->cAttr);
6166         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6167          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6168         ok(attributes->rgAttr[0].cValue == 0,
6169          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6170         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6171          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6172         ok(attributes->rgAttr[1].cValue == 1,
6173          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6174         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6175          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6176         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6177          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6178         LocalFree(buf);
6179     }
6180 }
6181
6182 static const BYTE singleCapability[] = {
6183 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6184 static const BYTE twoCapabilities[] = {
6185 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6186 static const BYTE singleCapabilitywithNULL[] = {
6187 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6188
6189 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6190 {
6191     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6192     BOOL ret;
6193     LPBYTE buf = NULL;
6194     DWORD size = 0;
6195     CRYPT_SMIME_CAPABILITY capability[2];
6196     CRYPT_SMIME_CAPABILITIES capabilities;
6197
6198     /* An empty capabilities is allowed */
6199     capabilities.cCapability = 0;
6200     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6201      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6202     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6203     if (buf)
6204     {
6205         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6206         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6207         LocalFree(buf);
6208     }
6209     /* A non-empty capabilities with an empty capability (lacking an OID) is
6210      * not allowed
6211      */
6212     capability[0].pszObjId = NULL;
6213     capability[0].Parameters.cbData = 0;
6214     capabilities.cCapability = 1;
6215     capabilities.rgCapability = capability;
6216     SetLastError(0xdeadbeef);
6217     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6218      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6219     ok(!ret && (GetLastError() == E_INVALIDARG ||
6220      GetLastError() == OSS_LIMITED /* Win9x */),
6221      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6222     capability[0].pszObjId = oid1;
6223     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6224      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6225     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6226     if (buf)
6227     {
6228         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6229         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6230         LocalFree(buf);
6231     }
6232     capability[1].pszObjId = oid2;
6233     capability[1].Parameters.cbData = 0;
6234     capabilities.cCapability = 2;
6235     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6236      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6237     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6238     if (buf)
6239     {
6240         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6241         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6242         LocalFree(buf);
6243     }
6244 }
6245
6246 static void compareSMimeCapabilities(LPCSTR header,
6247  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6248 {
6249     DWORD i;
6250
6251     ok(got->cCapability == expected->cCapability,
6252      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6253      got->cCapability);
6254     for (i = 0; i < expected->cCapability; i++)
6255     {
6256         ok(!strcmp(expected->rgCapability[i].pszObjId,
6257          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6258          header, i, expected->rgCapability[i].pszObjId,
6259          got->rgCapability[i].pszObjId);
6260         ok(expected->rgCapability[i].Parameters.cbData ==
6261          got->rgCapability[i].Parameters.cbData,
6262          "%s[%d]: expected %d bytes, got %d\n", header, i,
6263          expected->rgCapability[i].Parameters.cbData,
6264          got->rgCapability[i].Parameters.cbData);
6265         if (expected->rgCapability[i].Parameters.cbData)
6266             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6267              got->rgCapability[i].Parameters.pbData,
6268              expected->rgCapability[i].Parameters.cbData),
6269              "%s[%d]: unexpected value\n", header, i);
6270     }
6271 }
6272
6273 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6274 {
6275     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6276     BOOL ret;
6277     DWORD size = 0;
6278     CRYPT_SMIME_CAPABILITY capability[2];
6279     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6280
6281     SetLastError(0xdeadbeef);
6282     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6283      emptySequence, sizeof(emptySequence),
6284      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6285     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6286     if (ret)
6287     {
6288         capabilities.cCapability = 0;
6289         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6290         LocalFree(ptr);
6291     }
6292     SetLastError(0xdeadbeef);
6293     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6294      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6295      &ptr, &size);
6296     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6297     if (ret)
6298     {
6299         capability[0].pszObjId = oid1;
6300         capability[0].Parameters.cbData = 0;
6301         capabilities.cCapability = 1;
6302         capabilities.rgCapability = capability;
6303         compareSMimeCapabilities("single capability", &capabilities, ptr);
6304         LocalFree(ptr);
6305     }
6306     SetLastError(0xdeadbeef);
6307     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6308      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6309      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6310     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6311     if (ret)
6312     {
6313         BYTE NULLparam[] = {0x05, 0x00};
6314         capability[0].pszObjId = oid1;
6315         capability[0].Parameters.cbData = 2;
6316         capability[0].Parameters.pbData = NULLparam;
6317         capabilities.cCapability = 1;
6318         capabilities.rgCapability = capability;
6319         compareSMimeCapabilities("single capability with NULL", &capabilities,
6320          ptr);
6321         LocalFree(ptr);
6322     }
6323     SetLastError(0xdeadbeef);
6324     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6325     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6326     &ptr, &size);
6327     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6328     if (ret)
6329     {
6330         capability[0].Parameters.cbData = 0;
6331         capability[1].pszObjId = oid2;
6332         capability[1].Parameters.cbData = 0;
6333         capabilities.cCapability = 2;
6334         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6335         LocalFree(ptr);
6336     }
6337 }
6338
6339 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6340  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6341  0x67 };
6342 static const BYTE minimalPKCSSigner[] = {
6343  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6344  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6345  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6346 static const BYTE PKCSSignerWithSerial[] = {
6347  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6348  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6349  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6350  0x00 };
6351 static const BYTE PKCSSignerWithHashAlgo[] = {
6352  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6353  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6354  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6355  0x00,0x04,0x00 };
6356 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6357  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6358  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6359  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6360  0x06,0x05,0x00,0x04,0x00 };
6361 static const BYTE PKCSSignerWithHash[] = {
6362  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6363  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6364  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6365  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6366  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6367 static const BYTE PKCSSignerWithAuthAttr[] = {
6368 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6369 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6370 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6371 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6372 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6373 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6374 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6375
6376 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6377 {
6378     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6379     BOOL ret;
6380     LPBYTE buf = NULL;
6381     DWORD size = 0;
6382     CMSG_SIGNER_INFO info = { 0 };
6383     char oid_common_name[] = szOID_COMMON_NAME;
6384     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6385      (LPBYTE)encodedCommonName };
6386     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6387
6388     SetLastError(0xdeadbeef);
6389     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6390      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6391     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6392     {
6393         skip("no PKCS7_SIGNER_INFO encode support\n");
6394         return;
6395     }
6396     ok(!ret && (GetLastError() == E_INVALIDARG ||
6397      GetLastError() == OSS_LIMITED /* Win9x */),
6398      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6399     /* To be encoded, a signer must have an issuer at least, and the encoding
6400      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6401      * see decoding tests.)
6402      */
6403     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6404     info.Issuer.pbData = encodedCommonNameNoNull;
6405     SetLastError(0xdeadbeef);
6406     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6407      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6408     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6409         ok(!ret && GetLastError() == E_INVALIDARG,
6410          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6411     else
6412     {
6413         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6414          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6415         if (buf)
6416         {
6417             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6418             if (size == sizeof(minimalPKCSSigner))
6419                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6420             else
6421                 ok(0, "Unexpected value\n");
6422             LocalFree(buf);
6423         }
6424     }
6425     info.SerialNumber.cbData = sizeof(serialNum);
6426     info.SerialNumber.pbData = (BYTE *)serialNum;
6427     SetLastError(0xdeadbeef);
6428     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6429      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6430     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6431         ok(!ret && GetLastError() == E_INVALIDARG,
6432          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6433     else
6434     {
6435         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6436          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6437         if (buf)
6438         {
6439             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6440              size);
6441             if (size == sizeof(PKCSSignerWithSerial))
6442                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6443                  "Unexpected value\n");
6444             else
6445                 ok(0, "Unexpected value\n");
6446             LocalFree(buf);
6447         }
6448     }
6449     info.HashAlgorithm.pszObjId = oid1;
6450     SetLastError(0xdeadbeef);
6451     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6452      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6453     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6454         ok(!ret && GetLastError() == E_INVALIDARG,
6455          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6456     else
6457     {
6458         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6459          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6460         if (buf)
6461         {
6462             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6463              size);
6464             if (size == sizeof(PKCSSignerWithHashAlgo))
6465                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6466                  "Unexpected value\n");
6467             else
6468                 ok(0, "Unexpected value\n");
6469             LocalFree(buf);
6470         }
6471     }
6472     info.HashEncryptionAlgorithm.pszObjId = oid2;
6473     SetLastError(0xdeadbeef);
6474     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6475      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6476     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6477         ok(!ret && GetLastError() == E_INVALIDARG,
6478          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6479     else
6480     {
6481         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6482         if (buf)
6483         {
6484             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6485              "Unexpected size %d\n", size);
6486             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6487                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6488                  "Unexpected value\n");
6489             else
6490                 ok(0, "Unexpected value\n");
6491             LocalFree(buf);
6492         }
6493     }
6494     info.EncryptedHash.cbData = sizeof(hash);
6495     info.EncryptedHash.pbData = (BYTE *)hash;
6496     SetLastError(0xdeadbeef);
6497     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6498      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6499     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6500         ok(!ret && GetLastError() == E_INVALIDARG,
6501          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6502     else
6503     {
6504         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6505         if (buf)
6506         {
6507             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6508              size);
6509             if (size == sizeof(PKCSSignerWithHash))
6510                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6511                  "Unexpected value\n");
6512             else
6513                 ok(0, "Unexpected value\n");
6514             LocalFree(buf);
6515         }
6516     }
6517     info.AuthAttrs.cAttr = 1;
6518     info.AuthAttrs.rgAttr = &attr;
6519     SetLastError(0xdeadbeef);
6520     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6521      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6522     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6523         ok(!ret && GetLastError() == E_INVALIDARG,
6524          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6525     else
6526     {
6527         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6528         if (buf)
6529         {
6530             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6531              size);
6532             if (size == sizeof(PKCSSignerWithAuthAttr))
6533                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6534                  "Unexpected value\n");
6535             else
6536                 ok(0, "Unexpected value\n");
6537             LocalFree(buf);
6538         }
6539     }
6540 }
6541
6542 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6543 {
6544     BOOL ret;
6545     LPBYTE buf = NULL;
6546     DWORD size = 0;
6547     CMSG_SIGNER_INFO *info;
6548
6549     /* A PKCS signer can't be decoded without a serial number. */
6550     SetLastError(0xdeadbeef);
6551     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6552      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6553      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6554     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6555      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6556      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6557      GetLastError());
6558     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6559      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6560      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6561     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6562      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6563     if (buf)
6564     {
6565         info = (CMSG_SIGNER_INFO *)buf;
6566         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6567          info->dwVersion);
6568         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6569          "Unexpected size %d\n", info->Issuer.cbData);
6570         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6571          info->Issuer.cbData), "Unexpected value\n");
6572         ok(info->SerialNumber.cbData == sizeof(serialNum),
6573          "Unexpected size %d\n", info->SerialNumber.cbData);
6574         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6575          "Unexpected value\n");
6576         LocalFree(buf);
6577     }
6578     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6579      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6580      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6581     if (buf)
6582     {
6583         info = (CMSG_SIGNER_INFO *)buf;
6584         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6585          info->dwVersion);
6586         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6587          "Unexpected size %d\n", info->Issuer.cbData);
6588         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6589          info->Issuer.cbData), "Unexpected value\n");
6590         ok(info->SerialNumber.cbData == sizeof(serialNum),
6591          "Unexpected size %d\n", info->SerialNumber.cbData);
6592         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6593          "Unexpected value\n");
6594         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6595          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6596         LocalFree(buf);
6597     }
6598     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6599      PKCSSignerWithHashAndEncryptionAlgo,
6600      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6601      NULL, &buf, &size);
6602     if (buf)
6603     {
6604         info = (CMSG_SIGNER_INFO *)buf;
6605         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6606          info->dwVersion);
6607         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6608          "Unexpected size %d\n", info->Issuer.cbData);
6609         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6610          info->Issuer.cbData), "Unexpected value\n");
6611         ok(info->SerialNumber.cbData == sizeof(serialNum),
6612          "Unexpected size %d\n", info->SerialNumber.cbData);
6613         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6614          "Unexpected value\n");
6615         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6616          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6617         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6618          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6619         LocalFree(buf);
6620     }
6621     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6622      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6623      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6624     if (buf)
6625     {
6626         info = (CMSG_SIGNER_INFO *)buf;
6627         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6628          info->dwVersion);
6629         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6630          "Unexpected size %d\n", info->Issuer.cbData);
6631         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6632          info->Issuer.cbData), "Unexpected value\n");
6633         ok(info->SerialNumber.cbData == sizeof(serialNum),
6634          "Unexpected size %d\n", info->SerialNumber.cbData);
6635         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6636          "Unexpected value\n");
6637         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6638          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6639         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6640          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6641         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6642          info->EncryptedHash.cbData);
6643         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6644          "Unexpected value\n");
6645         LocalFree(buf);
6646     }
6647     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6648      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6649      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6650     if (buf)
6651     {
6652         info = (CMSG_SIGNER_INFO *)buf;
6653         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6654          info->AuthAttrs.cAttr);
6655         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6656          "Expected %s, got %s\n", szOID_COMMON_NAME,
6657          info->AuthAttrs.rgAttr[0].pszObjId);
6658         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6659          info->AuthAttrs.rgAttr[0].cValue);
6660         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6661          sizeof(encodedCommonName), "Unexpected size %d\n",
6662          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6663         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6664          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6665         LocalFree(buf);
6666     }
6667 }
6668
6669 static const BYTE CMSSignerWithKeyId[] = {
6670 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6671 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6672
6673 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6674 {
6675     BOOL ret;
6676     LPBYTE buf = NULL;
6677     DWORD size = 0;
6678     CMSG_CMS_SIGNER_INFO info = { 0 };
6679     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6680
6681     SetLastError(0xdeadbeef);
6682     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6683      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6684     ok(!ret, "Expected failure, got %d\n", ret);
6685     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6686     {
6687         skip("no CMS_SIGNER_INFO encode support\n");
6688         return;
6689     }
6690     ok(GetLastError() == E_INVALIDARG,
6691        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6692     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6693     SetLastError(0xdeadbeef);
6694     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6695      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6696     ok(!ret, "Expected failure, got %d\n", ret);
6697     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6698     {
6699         skip("no CMS_SIGNER_INFO encode support\n");
6700         return;
6701     }
6702     ok(GetLastError() == E_INVALIDARG,
6703        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6704     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6705      * be a key id or a issuer serial number with at least the issuer set, and
6706      * the encoding must include PKCS_7_ASN_ENCODING.
6707      * (That isn't enough to be decoded, see decoding tests.)
6708      */
6709     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6710      sizeof(encodedCommonNameNoNull);
6711     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6712     SetLastError(0xdeadbeef);
6713     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6714      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6715     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6716         ok(!ret && GetLastError() == E_INVALIDARG,
6717          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6718     else
6719     {
6720         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6721         if (buf)
6722         {
6723             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6724             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6725             LocalFree(buf);
6726         }
6727     }
6728     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6729     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6730     SetLastError(0xdeadbeef);
6731     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6732      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6733     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6734         ok(!ret && GetLastError() == E_INVALIDARG,
6735          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6736     else
6737     {
6738         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6739         if (buf)
6740         {
6741             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6742              size);
6743             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6744             LocalFree(buf);
6745         }
6746     }
6747     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6748     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6749     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6750     SetLastError(0xdeadbeef);
6751     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6752      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6753     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6754         ok(!ret && GetLastError() == E_INVALIDARG,
6755          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6756     else
6757     {
6758         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6759         if (buf)
6760         {
6761             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6762              size);
6763             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6764             LocalFree(buf);
6765         }
6766     }
6767     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6768      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6769      * (see RFC 3852, section 5.3.)
6770      */
6771     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6772     U(info.SignerId).HashId.cbData = sizeof(hash);
6773     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6774     SetLastError(0xdeadbeef);
6775     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6776      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6777     ok(!ret && GetLastError() == E_INVALIDARG,
6778      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6779     /* Now with a hash algo */
6780     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6781     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6782      sizeof(encodedCommonNameNoNull);
6783     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6784     info.HashAlgorithm.pszObjId = oid1;
6785     SetLastError(0xdeadbeef);
6786     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6787      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6788     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6789         ok(!ret && GetLastError() == E_INVALIDARG,
6790          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6791     else
6792     {
6793         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6794         if (buf)
6795         {
6796             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6797              size);
6798             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6799              "Unexpected value\n");
6800             LocalFree(buf);
6801         }
6802     }
6803     info.HashEncryptionAlgorithm.pszObjId = oid2;
6804     SetLastError(0xdeadbeef);
6805     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6806      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6807     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6808         ok(!ret && GetLastError() == E_INVALIDARG,
6809          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6810     else
6811     {
6812         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6813         if (buf)
6814         {
6815             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6816              "Unexpected size %d\n", size);
6817             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6818              "Unexpected value\n");
6819             LocalFree(buf);
6820         }
6821     }
6822     info.EncryptedHash.cbData = sizeof(hash);
6823     info.EncryptedHash.pbData = (BYTE *)hash;
6824     SetLastError(0xdeadbeef);
6825     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6826      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6827     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6828         ok(!ret && GetLastError() == E_INVALIDARG,
6829          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6830     else
6831     {
6832         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6833         if (buf)
6834         {
6835             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6836              size);
6837             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6838             LocalFree(buf);
6839         }
6840     }
6841 }
6842
6843 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6844 {
6845     BOOL ret;
6846     LPBYTE buf = NULL;
6847     DWORD size = 0;
6848     CMSG_CMS_SIGNER_INFO *info;
6849     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6850
6851     /* A CMS signer can't be decoded without a serial number. */
6852     SetLastError(0xdeadbeef);
6853     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6854      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6855      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6856     ok(!ret, "expected failure\n");
6857     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6858     {
6859         skip("no CMS_SIGNER_INFO decode support\n");
6860         return;
6861     }
6862     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6863      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6864     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6865      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6866      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6867     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6868     if (buf)
6869     {
6870         info = (CMSG_CMS_SIGNER_INFO *)buf;
6871         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6872          info->dwVersion);
6873         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6874          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6875          info->SignerId.dwIdChoice);
6876         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6877          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6878          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6879         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6880          encodedCommonNameNoNull,
6881          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6882          "Unexpected value\n");
6883         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6884          sizeof(serialNum), "Unexpected size %d\n",
6885          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6886         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6887          serialNum, sizeof(serialNum)), "Unexpected value\n");
6888         LocalFree(buf);
6889     }
6890     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6891      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6892      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6893     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6894     if (buf)
6895     {
6896         info = (CMSG_CMS_SIGNER_INFO *)buf;
6897         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6898          info->dwVersion);
6899         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6900          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6901          info->SignerId.dwIdChoice);
6902         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6903          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6904          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6905         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6906          encodedCommonNameNoNull,
6907          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6908          "Unexpected value\n");
6909         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6910          sizeof(serialNum), "Unexpected size %d\n",
6911          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6912         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6913          serialNum, sizeof(serialNum)), "Unexpected value\n");
6914         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6915          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6916         LocalFree(buf);
6917     }
6918     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6919      PKCSSignerWithHashAndEncryptionAlgo,
6920      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6921      NULL, &buf, &size);
6922     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6923     if (buf)
6924     {
6925         info = (CMSG_CMS_SIGNER_INFO *)buf;
6926         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6927          info->dwVersion);
6928         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6929          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6930          info->SignerId.dwIdChoice);
6931         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6932          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6933          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6934         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6935          encodedCommonNameNoNull,
6936          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6937          "Unexpected value\n");
6938         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6939          sizeof(serialNum), "Unexpected size %d\n",
6940          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6941         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6942          serialNum, sizeof(serialNum)), "Unexpected value\n");
6943         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6944          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6945         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6946          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6947         LocalFree(buf);
6948     }
6949     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6950      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6951      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6952     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6953     if (buf)
6954     {
6955         info = (CMSG_CMS_SIGNER_INFO *)buf;
6956         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6957          info->dwVersion);
6958         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6959          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6960          info->SignerId.dwIdChoice);
6961         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6962          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6963          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6964         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6965          encodedCommonNameNoNull,
6966          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6967          "Unexpected value\n");
6968         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6969          sizeof(serialNum), "Unexpected size %d\n",
6970          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6971         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6972          serialNum, sizeof(serialNum)), "Unexpected value\n");
6973         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6974          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6975         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6976          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6977         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6978          info->EncryptedHash.cbData);
6979         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6980          "Unexpected value\n");
6981         LocalFree(buf);
6982     }
6983     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6984      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6985      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6986     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6987     if (buf)
6988     {
6989         info = (CMSG_CMS_SIGNER_INFO *)buf;
6990         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6991          info->dwVersion);
6992         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6993          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6994          info->SignerId.dwIdChoice);
6995         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6996          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6997         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6998          "Unexpected value\n");
6999         LocalFree(buf);
7000     }
7001 }
7002
7003 static BYTE emptyDNSPermittedConstraints[] = {
7004 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7005 static BYTE emptyDNSExcludedConstraints[] = {
7006 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7007 static BYTE DNSExcludedConstraints[] = {
7008 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7009 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7010 static BYTE permittedAndExcludedConstraints[] = {
7011 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7012 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7013 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7014 static BYTE permittedAndExcludedWithMinConstraints[] = {
7015 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7016 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7017 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7018 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7019 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7020 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7021 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7022
7023 static void test_encodeNameConstraints(DWORD dwEncoding)
7024 {
7025     BOOL ret;
7026     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7027     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7028     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7029     LPBYTE buf;
7030     DWORD size;
7031
7032     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7033      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7034     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7035     {
7036         skip("no X509_NAME_CONSTRAINTS encode support\n");
7037         return;
7038     }
7039     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7040     if (ret)
7041     {
7042         ok(size == sizeof(emptySequence), "Unexpected size\n");
7043         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7044         LocalFree(buf);
7045     }
7046     constraints.cPermittedSubtree = 1;
7047     constraints.rgPermittedSubtree = &permitted;
7048     SetLastError(0xdeadbeef);
7049     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7050      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7051     ok(!ret && GetLastError() == E_INVALIDARG,
7052      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7053     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7054     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7055      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7056     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7057     if (ret)
7058     {
7059         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7060         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7061          "Unexpected value\n");
7062         LocalFree(buf);
7063     }
7064     constraints.cPermittedSubtree = 0;
7065     constraints.cExcludedSubtree = 1;
7066     constraints.rgExcludedSubtree = &excluded;
7067     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7068     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7069      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7070     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7071     if (ret)
7072     {
7073         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7074         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7075          "Unexpected value\n");
7076         LocalFree(buf);
7077     }
7078     U(excluded.Base).pwszURL = (LPWSTR)url;
7079     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7080      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7081     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7082     if (ret)
7083     {
7084         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7085         ok(!memcmp(buf, DNSExcludedConstraints, size),
7086          "Unexpected value\n");
7087         LocalFree(buf);
7088     }
7089     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7090     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7091     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7092     constraints.cPermittedSubtree = 1;
7093     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7094      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7095     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7096     if (ret)
7097     {
7098         ok(size == sizeof(permittedAndExcludedConstraints),
7099          "Unexpected size\n");
7100         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7101          "Unexpected value\n");
7102         LocalFree(buf);
7103     }
7104     permitted.dwMinimum = 5;
7105     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7107     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7108     if (ret)
7109     {
7110         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7111          "Unexpected size\n");
7112         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7113          "Unexpected value\n");
7114         LocalFree(buf);
7115     }
7116     permitted.fMaximum = TRUE;
7117     permitted.dwMaximum = 3;
7118     SetLastError(0xdeadbeef);
7119     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7120      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7121     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7122     if (ret)
7123     {
7124         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7125          "Unexpected size\n");
7126         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7127          "Unexpected value\n");
7128         LocalFree(buf);
7129     }
7130 }
7131
7132 struct EncodedNameConstraints
7133 {
7134     CRYPT_DATA_BLOB            encoded;
7135     CERT_NAME_CONSTRAINTS_INFO constraints;
7136 };
7137
7138 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7139  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7140 static CERT_GENERAL_SUBTREE DNSSubtree = {
7141  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7142 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7143  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7144 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7145  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7146 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7147  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7148
7149 struct EncodedNameConstraints encodedNameConstraints[] = {
7150  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7151  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7152    { 1, &emptyDNSSubtree, 0, NULL } },
7153  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7154    { 0, NULL, 1, &emptyDNSSubtree } },
7155  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7156    { 0, NULL, 1, &DNSSubtree } },
7157  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7158    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7159  { { sizeof(permittedAndExcludedWithMinConstraints),
7160      permittedAndExcludedWithMinConstraints },
7161    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7162  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7163      permittedAndExcludedWithMinMaxConstraints },
7164    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7165 };
7166
7167 static void test_decodeNameConstraints(DWORD dwEncoding)
7168 {
7169     BOOL ret;
7170     DWORD i;
7171     CERT_NAME_CONSTRAINTS_INFO *constraints;
7172
7173     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7174     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7175     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7176     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7177     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7178     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7179     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7180     for (i = 0;
7181      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7182      i++)
7183     {
7184         DWORD size;
7185
7186         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7187          encodedNameConstraints[i].encoded.pbData,
7188          encodedNameConstraints[i].encoded.cbData,
7189          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7190         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7191         {
7192             skip("no X509_NAME_CONSTRAINTS decode support\n");
7193             return;
7194         }
7195         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7196         if (ret)
7197         {
7198             DWORD j;
7199
7200             if (constraints->cPermittedSubtree !=
7201              encodedNameConstraints[i].constraints.cPermittedSubtree)
7202                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7203                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7204                  constraints->cPermittedSubtree);
7205             if (constraints->cPermittedSubtree ==
7206              encodedNameConstraints[i].constraints.cPermittedSubtree)
7207             {
7208                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7209                 {
7210                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7211                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7212                 }
7213             }
7214             if (constraints->cExcludedSubtree !=
7215              encodedNameConstraints[i].constraints.cExcludedSubtree)
7216                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7217                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7218                  constraints->cExcludedSubtree);
7219             if (constraints->cExcludedSubtree ==
7220              encodedNameConstraints[i].constraints.cExcludedSubtree)
7221             {
7222                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7223                 {
7224                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7225                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7226                 }
7227             }
7228             LocalFree(constraints);
7229         }
7230     }
7231 }
7232
7233 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7234  'n','o','t','i','c','e',0 };
7235 static const BYTE noticeWithDisplayText[] = {
7236  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7237  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7238  0x00,0x69,0x00,0x63,0x00,0x65
7239 };
7240 static char org[] = "Wine";
7241 static int noticeNumbers[] = { 2,3 };
7242 static BYTE noticeWithReference[] = {
7243  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7244  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7245  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7246  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7247 };
7248
7249 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7250 {
7251     BOOL ret;
7252     LPBYTE buf;
7253     DWORD size;
7254     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7255     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7256
7257     memset(&notice, 0, sizeof(notice));
7258     ret = pCryptEncodeObjectEx(dwEncoding,
7259      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7260      NULL, &buf, &size);
7261     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7262     {
7263         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7264         return;
7265     }
7266     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7267     if (ret)
7268     {
7269         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7270         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7271         LocalFree(buf);
7272     }
7273     notice.pszDisplayText = noticeText;
7274     ret = pCryptEncodeObjectEx(dwEncoding,
7275      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7276      NULL, &buf, &size);
7277     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7278     if (ret)
7279     {
7280         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7281         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7282         LocalFree(buf);
7283     }
7284     reference.pszOrganization = org;
7285     reference.cNoticeNumbers = 2;
7286     reference.rgNoticeNumbers = noticeNumbers;
7287     notice.pNoticeReference = &reference;
7288     ret = pCryptEncodeObjectEx(dwEncoding,
7289      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7290      NULL, &buf, &size);
7291     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7292     if (ret)
7293     {
7294         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7295         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7296         LocalFree(buf);
7297     }
7298 }
7299
7300 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7301 {
7302     BOOL ret;
7303     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7304     DWORD size;
7305
7306     ret = pCryptDecodeObjectEx(dwEncoding,
7307      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7308      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7309      &notice, &size);
7310     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7311     {
7312         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7313         return;
7314     }
7315     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7316     if (ret)
7317     {
7318         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7319         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7320         LocalFree(notice);
7321     }
7322     ret = pCryptDecodeObjectEx(dwEncoding,
7323      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7324      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7325      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7326     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7327     if (ret)
7328     {
7329         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7330          "unexpected display text\n");
7331         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7332         LocalFree(notice);
7333     }
7334     ret = pCryptDecodeObjectEx(dwEncoding,
7335      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7336      noticeWithReference, sizeof(noticeWithReference),
7337      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7338     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7339     if (ret)
7340     {
7341         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7342          "unexpected display text\n");
7343         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7344         if (notice->pNoticeReference)
7345         {
7346             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7347              "unexpected organization %s\n",
7348              notice->pNoticeReference->pszOrganization);
7349             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7350              "expected 2 notice numbers, got %d\n",
7351              notice->pNoticeReference->cNoticeNumbers);
7352             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7353              "unexpected notice number %d\n",
7354              notice->pNoticeReference->rgNoticeNumbers[0]);
7355             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7356              "unexpected notice number %d\n",
7357              notice->pNoticeReference->rgNoticeNumbers[1]);
7358         }
7359         LocalFree(notice);
7360     }
7361 }
7362
7363 static char oid_any_policy[] = "2.5.29.32.0";
7364 static const BYTE policiesWithAnyPolicy[] = {
7365  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7366 };
7367 static char oid1[] = "1.2.3";
7368 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7369 static const BYTE twoPolicies[] = {
7370  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7371  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7372  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7373  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7374  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7375  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7376 };
7377
7378 static void test_encodeCertPolicies(DWORD dwEncoding)
7379 {
7380     BOOL ret;
7381     CERT_POLICIES_INFO info;
7382     CERT_POLICY_INFO policy[2];
7383     CERT_POLICY_QUALIFIER_INFO qualifier;
7384     LPBYTE buf;
7385     DWORD size;
7386
7387     memset(&info, 0, sizeof(info));
7388     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7389      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7390     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7391     if (ret)
7392     {
7393         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7394         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7395         LocalFree(buf);
7396     }
7397     memset(policy, 0, sizeof(policy));
7398     info.cPolicyInfo = 1;
7399     info.rgPolicyInfo = policy;
7400     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7401      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7402     ok(!ret && (GetLastError() == E_INVALIDARG ||
7403      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7404      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7405     policy[0].pszPolicyIdentifier = oid_any_policy;
7406     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7407      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7408     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7409     if (ret)
7410     {
7411         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7412         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7413         LocalFree(buf);
7414     }
7415     policy[1].pszPolicyIdentifier = oid1;
7416     memset(&qualifier, 0, sizeof(qualifier));
7417     qualifier.pszPolicyQualifierId = oid_user_notice;
7418     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7419     qualifier.Qualifier.pbData = noticeWithReference;
7420     policy[1].cPolicyQualifier = 1;
7421     policy[1].rgPolicyQualifier = &qualifier;
7422     info.cPolicyInfo = 2;
7423     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7424      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7425     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7426     if (ret)
7427     {
7428         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7429         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7430         LocalFree(buf);
7431     }
7432 }
7433
7434 static void test_decodeCertPolicies(DWORD dwEncoding)
7435 {
7436     BOOL ret;
7437     CERT_POLICIES_INFO *info;
7438     DWORD size;
7439
7440     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7441      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7442      &info, &size);
7443     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7444     if (ret)
7445     {
7446         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7447          info->cPolicyInfo);
7448         LocalFree(info);
7449     }
7450     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7451      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7452      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7453     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7454     if (ret)
7455     {
7456         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7457          info->cPolicyInfo);
7458         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7459          "unexpected policy id %s\n",
7460          info->rgPolicyInfo[0].pszPolicyIdentifier);
7461         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7462          "unexpected policy qualifier count %d\n",
7463          info->rgPolicyInfo[0].cPolicyQualifier);
7464         LocalFree(info);
7465     }
7466     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7467      twoPolicies, sizeof(twoPolicies),
7468      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7469     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7470     if (ret)
7471     {
7472         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7473          info->cPolicyInfo);
7474         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7475          "unexpected policy id %s\n",
7476          info->rgPolicyInfo[0].pszPolicyIdentifier);
7477         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7478          "unexpected policy qualifier count %d\n",
7479          info->rgPolicyInfo[0].cPolicyQualifier);
7480         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7481          "unexpected policy id %s\n",
7482          info->rgPolicyInfo[1].pszPolicyIdentifier);
7483         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7484          "unexpected policy qualifier count %d\n",
7485          info->rgPolicyInfo[1].cPolicyQualifier);
7486         ok(!strcmp(
7487          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7488          oid_user_notice), "unexpected policy qualifier id %s\n",
7489          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7490         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7491          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7492          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7493         ok(!memcmp(
7494          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7495          noticeWithReference, sizeof(noticeWithReference)),
7496          "unexpected qualifier value\n");
7497         LocalFree(info);
7498     }
7499 }
7500
7501 static const BYTE policyMappingWithOneMapping[] = {
7502 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7503 static const BYTE policyMappingWithTwoMappings[] = {
7504 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7505 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7506 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7507  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7508
7509 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7510 {
7511     static char oid2[] = "2.3.4";
7512     static char oid3[] = "1.3.4";
7513     static char oid4[] = "2.5.6";
7514     BOOL ret;
7515     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7516     CERT_POLICY_MAPPING mapping[2];
7517     LPBYTE buf;
7518     DWORD size, i;
7519
7520     /* Each of the mapping OIDs is equivalent, so check with all of them */
7521     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7522     {
7523         memset(&info, 0, sizeof(info));
7524         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7525          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7526         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7527         if (ret)
7528         {
7529             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7530             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7531              "unexpected value\n");
7532             LocalFree(buf);
7533         }
7534         mapping[0].pszIssuerDomainPolicy = NULL;
7535         mapping[0].pszSubjectDomainPolicy = NULL;
7536         info.cPolicyMapping = 1;
7537         info.rgPolicyMapping = mapping;
7538         SetLastError(0xdeadbeef);
7539         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7540          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7541         ok(!ret && GetLastError() == E_INVALIDARG,
7542          "expected E_INVALIDARG, got %08x\n", GetLastError());
7543         mapping[0].pszIssuerDomainPolicy = oid1;
7544         mapping[0].pszSubjectDomainPolicy = oid2;
7545         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7546          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7547         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7548         if (ret)
7549         {
7550             ok(size == sizeof(policyMappingWithOneMapping),
7551              "unexpected size %d\n", size);
7552             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7553              "unexpected value\n");
7554             LocalFree(buf);
7555         }
7556         mapping[1].pszIssuerDomainPolicy = oid3;
7557         mapping[1].pszSubjectDomainPolicy = oid4;
7558         info.cPolicyMapping = 2;
7559         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7560          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7561         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7562         if (ret)
7563         {
7564             ok(size == sizeof(policyMappingWithTwoMappings),
7565              "unexpected size %d\n", size);
7566             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7567              "unexpected value\n");
7568             LocalFree(buf);
7569         }
7570     }
7571 }
7572
7573 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7574 {
7575     DWORD size, i;
7576     CERT_POLICY_MAPPINGS_INFO *info;
7577     BOOL ret;
7578
7579     /* Each of the mapping OIDs is equivalent, so check with all of them */
7580     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7581     {
7582         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7583          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7584          &info, &size);
7585         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7586         if (ret)
7587         {
7588             ok(info->cPolicyMapping == 0,
7589              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7590             LocalFree(info);
7591         }
7592         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7593          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7594          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7595         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7596         if (ret)
7597         {
7598             ok(info->cPolicyMapping == 1,
7599              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7600             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7601              "unexpected issuer policy %s\n",
7602              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7603             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7604              "2.3.4"), "unexpected subject policy %s\n",
7605              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7606             LocalFree(info);
7607         }
7608         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7609          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7610          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7611         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7612         if (ret)
7613         {
7614             ok(info->cPolicyMapping == 2,
7615              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7616             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7617              "unexpected issuer policy %s\n",
7618              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7619             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7620              "2.3.4"), "unexpected subject policy %s\n",
7621              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7622             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7623              "unexpected issuer policy %s\n",
7624              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7625             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7626              "2.5.6"), "unexpected subject policy %s\n",
7627              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7628             LocalFree(info);
7629         }
7630     }
7631 }
7632
7633 static const BYTE policyConstraintsWithRequireExplicit[] = {
7634 0x30,0x03,0x80,0x01,0x00 };
7635 static const BYTE policyConstraintsWithInhibitMapping[] = {
7636 0x30,0x03,0x81,0x01,0x01 };
7637 static const BYTE policyConstraintsWithBoth[] = {
7638 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7639
7640 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7641 {
7642     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7643     LPBYTE buf;
7644     DWORD size;
7645     BOOL ret;
7646
7647     /* Even though RFC 5280 explicitly states CAs must not issue empty
7648      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7649      */
7650     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7651      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7652     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7653     if (ret)
7654     {
7655         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7656         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7657          "unexpected value\n");
7658         LocalFree(buf);
7659     }
7660     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7661      * is not, then a skip of 0 is encoded.
7662      */
7663     info.fRequireExplicitPolicy = TRUE;
7664     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7665      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7666     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7667     if (ret)
7668     {
7669         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7670          "unexpected size %d\n", size);
7671         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7672          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7673         LocalFree(buf);
7674     }
7675     /* With inhibit policy mapping */
7676     info.fRequireExplicitPolicy = FALSE;
7677     info.dwRequireExplicitPolicySkipCerts = 0;
7678     info.fInhibitPolicyMapping = TRUE;
7679     info.dwInhibitPolicyMappingSkipCerts = 1;
7680     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7681      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7682     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7683     if (ret)
7684     {
7685         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7686          "unexpected size %d\n", size);
7687         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7688          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7689         LocalFree(buf);
7690     }
7691     /* And with both */
7692     info.fRequireExplicitPolicy = TRUE;
7693     info.dwRequireExplicitPolicySkipCerts = 1;
7694     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7695      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7696     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7697     if (ret)
7698     {
7699         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7700          size);
7701         ok(!memcmp(buf, policyConstraintsWithBoth,
7702          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7703         LocalFree(buf);
7704     }
7705 }
7706
7707 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7708 {
7709     CERT_POLICY_CONSTRAINTS_INFO *info;
7710     DWORD size;
7711     BOOL ret;
7712
7713     /* Again, even though CAs must not issue such constraints, they can be
7714      * decoded.
7715      */
7716     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7717      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7718      &info, &size);
7719     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7720     if (ret)
7721     {
7722         ok(!info->fRequireExplicitPolicy,
7723          "expected require explicit = FALSE\n");
7724         ok(!info->fInhibitPolicyMapping,
7725          "expected implicit mapping = FALSE\n");
7726         LocalFree(info);
7727     }
7728     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7729      policyConstraintsWithRequireExplicit,
7730      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7731      NULL, &info, &size);
7732     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7733     if (ret)
7734     {
7735         ok(info->fRequireExplicitPolicy,
7736          "expected require explicit = TRUE\n");
7737         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7738          info->dwRequireExplicitPolicySkipCerts);
7739         ok(!info->fInhibitPolicyMapping,
7740          "expected implicit mapping = FALSE\n");
7741         LocalFree(info);
7742     }
7743     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7744      policyConstraintsWithInhibitMapping,
7745      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7746      NULL, &info, &size);
7747     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7748     if (ret)
7749     {
7750         ok(!info->fRequireExplicitPolicy,
7751          "expected require explicit = FALSE\n");
7752         ok(info->fInhibitPolicyMapping,
7753          "expected implicit mapping = TRUE\n");
7754         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7755          info->dwInhibitPolicyMappingSkipCerts);
7756         LocalFree(info);
7757     }
7758     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7759      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7760      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7761     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7762     if (ret)
7763     {
7764         ok(info->fRequireExplicitPolicy,
7765          "expected require explicit = TRUE\n");
7766         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7767          info->dwRequireExplicitPolicySkipCerts);
7768         ok(info->fInhibitPolicyMapping,
7769          "expected implicit mapping = TRUE\n");
7770         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7771          info->dwInhibitPolicyMappingSkipCerts);
7772         LocalFree(info);
7773     }
7774 }
7775
7776 /* Free *pInfo with HeapFree */
7777 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7778 {
7779     BOOL ret;
7780     DWORD size = 0;
7781     HCRYPTKEY key;
7782
7783     /* This crashes
7784     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7785      */
7786     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7787     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7788      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7789     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7790      &size);
7791     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7792      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7793     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7794      NULL, &size);
7795     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7796      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7797     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7798      0, NULL, NULL, &size);
7799     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7800      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7801     /* Test with no key */
7802     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7803      0, NULL, NULL, &size);
7804     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7805      GetLastError());
7806     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7807     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7808     if (ret)
7809     {
7810         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7811          NULL, 0, NULL, NULL, &size);
7812         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7813         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7814         if (*pInfo)
7815         {
7816             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7817              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7818             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7819              GetLastError());
7820             if (ret)
7821             {
7822                 /* By default (we passed NULL as the OID) the OID is
7823                  * szOID_RSA_RSA.
7824                  */
7825                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7826                  "Expected %s, got %s\n", szOID_RSA_RSA,
7827                  (*pInfo)->Algorithm.pszObjId);
7828             }
7829         }
7830     }
7831     CryptDestroyKey(key);
7832 }
7833
7834 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7835  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7836  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7837  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7838  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7839  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7840  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7841  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7842  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7843  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7844  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7845  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7846  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7847  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7848  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7849  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7850  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7851  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7852  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7853  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7854  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7855  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7856  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7857  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7858  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7859
7860 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7861 {
7862     BOOL ret;
7863     HCRYPTKEY key;
7864     PCCERT_CONTEXT context;
7865     DWORD dwSize;
7866     ALG_ID ai;
7867
7868     /* These crash
7869     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7870     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7871     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7872     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7873      NULL);
7874      */
7875     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7876     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7877      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7878     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7879     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7880      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7881     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7882      &key);
7883     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7884      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7885
7886     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7887     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7888      &key);
7889     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7890
7891     dwSize = sizeof(ai);
7892     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7893     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7894     if(ret)
7895     {
7896       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7897       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7898     }
7899
7900     CryptDestroyKey(key);
7901
7902     /* Repeat with forced algorithm */
7903     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7904      &key);
7905     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7906
7907     dwSize = sizeof(ai);
7908     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7909     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7910     if(ret)
7911     {
7912       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7913       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7914     }
7915
7916     CryptDestroyKey(key);
7917
7918     /* Test importing a public key from a certificate context */
7919     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7920      sizeof(expiredCert));
7921     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7922      GetLastError());
7923     if (context)
7924     {
7925         ok(!strcmp(szOID_RSA_RSA,
7926          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7927          "Expected %s, got %s\n", szOID_RSA_RSA,
7928          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7929         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7930          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7931         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7932         CryptDestroyKey(key);
7933         CertFreeCertificateContext(context);
7934     }
7935 }
7936
7937 static const char cspName[] = "WineCryptTemp";
7938
7939 static void testPortPublicKeyInfo(void)
7940 {
7941     HCRYPTPROV csp;
7942     BOOL ret;
7943     PCERT_PUBLIC_KEY_INFO info = NULL;
7944
7945     /* Just in case a previous run failed, delete this thing */
7946     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7947      CRYPT_DELETEKEYSET);
7948     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7949      CRYPT_NEWKEYSET);
7950
7951     testExportPublicKey(csp, &info);
7952     testImportPublicKey(csp, info);
7953
7954     HeapFree(GetProcessHeap(), 0, info);
7955     CryptReleaseContext(csp, 0);
7956     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7957      CRYPT_DELETEKEYSET);
7958 }
7959
7960 START_TEST(encode)
7961 {
7962     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7963      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7964     HMODULE hCrypt32;
7965     DWORD i;
7966
7967     hCrypt32 = GetModuleHandleA("crypt32.dll");
7968     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7969     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7970     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7971     {
7972         win_skip("CryptDecodeObjectEx() is not available\n");
7973         return;
7974     }
7975
7976     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7977     {
7978         test_encodeInt(encodings[i]);
7979         test_decodeInt(encodings[i]);
7980         test_encodeEnumerated(encodings[i]);
7981         test_decodeEnumerated(encodings[i]);
7982         test_encodeFiletime(encodings[i]);
7983         test_decodeFiletime(encodings[i]);
7984         test_encodeName(encodings[i]);
7985         test_decodeName(encodings[i]);
7986         test_encodeUnicodeName(encodings[i]);
7987         test_decodeUnicodeName(encodings[i]);
7988         test_encodeNameValue(encodings[i]);
7989         test_decodeNameValue(encodings[i]);
7990         test_encodeUnicodeNameValue(encodings[i]);
7991         test_decodeUnicodeNameValue(encodings[i]);
7992         test_encodeAltName(encodings[i]);
7993         test_decodeAltName(encodings[i]);
7994         test_encodeOctets(encodings[i]);
7995         test_decodeOctets(encodings[i]);
7996         test_encodeBits(encodings[i]);
7997         test_decodeBits(encodings[i]);
7998         test_encodeBasicConstraints(encodings[i]);
7999         test_decodeBasicConstraints(encodings[i]);
8000         test_encodeRsaPublicKey(encodings[i]);
8001         test_decodeRsaPublicKey(encodings[i]);
8002         test_encodeSequenceOfAny(encodings[i]);
8003         test_decodeSequenceOfAny(encodings[i]);
8004         test_encodeExtensions(encodings[i]);
8005         test_decodeExtensions(encodings[i]);
8006         test_encodePublicKeyInfo(encodings[i]);
8007         test_decodePublicKeyInfo(encodings[i]);
8008         test_encodeCertToBeSigned(encodings[i]);
8009         test_decodeCertToBeSigned(encodings[i]);
8010         test_encodeCert(encodings[i]);
8011         test_decodeCert(encodings[i]);
8012         test_encodeCRLDistPoints(encodings[i]);
8013         test_decodeCRLDistPoints(encodings[i]);
8014         test_encodeCRLIssuingDistPoint(encodings[i]);
8015         test_decodeCRLIssuingDistPoint(encodings[i]);
8016         test_encodeCRLToBeSigned(encodings[i]);
8017         test_decodeCRLToBeSigned(encodings[i]);
8018         test_encodeEnhancedKeyUsage(encodings[i]);
8019         test_decodeEnhancedKeyUsage(encodings[i]);
8020         test_encodeAuthorityKeyId(encodings[i]);
8021         test_decodeAuthorityKeyId(encodings[i]);
8022         test_encodeAuthorityKeyId2(encodings[i]);
8023         test_decodeAuthorityKeyId2(encodings[i]);
8024         test_encodeAuthorityInfoAccess(encodings[i]);
8025         test_decodeAuthorityInfoAccess(encodings[i]);
8026         test_encodeCTL(encodings[i]);
8027         test_decodeCTL(encodings[i]);
8028         test_encodePKCSContentInfo(encodings[i]);
8029         test_decodePKCSContentInfo(encodings[i]);
8030         test_encodePKCSAttribute(encodings[i]);
8031         test_decodePKCSAttribute(encodings[i]);
8032         test_encodePKCSAttributes(encodings[i]);
8033         test_decodePKCSAttributes(encodings[i]);
8034         test_encodePKCSSMimeCapabilities(encodings[i]);
8035         test_decodePKCSSMimeCapabilities(encodings[i]);
8036         test_encodePKCSSignerInfo(encodings[i]);
8037         test_decodePKCSSignerInfo(encodings[i]);
8038         test_encodeCMSSignerInfo(encodings[i]);
8039         test_decodeCMSSignerInfo(encodings[i]);
8040         test_encodeNameConstraints(encodings[i]);
8041         test_decodeNameConstraints(encodings[i]);
8042         test_encodePolicyQualifierUserNotice(encodings[i]);
8043         test_decodePolicyQualifierUserNotice(encodings[i]);
8044         test_encodeCertPolicies(encodings[i]);
8045         test_decodeCertPolicies(encodings[i]);
8046         test_encodeCertPolicyMappings(encodings[i]);
8047         test_decodeCertPolicyMappings(encodings[i]);
8048         test_encodeCertPolicyConstraints(encodings[i]);
8049         test_decodeCertPolicyConstraints(encodings[i]);
8050     }
8051     testPortPublicKeyInfo();
8052 }