crypt32/tests: Add a trailing '\n' to ok() calls.
[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     /* Some Windows versions disallow name values with embedded NULLs, so
1391      * either success or failure is acceptable.
1392      */
1393     if (ret)
1394     {
1395         CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1396          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1397         CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1398          { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1399         const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1400          *expected = NULL;
1401
1402         /* Some Windows versions decode name values with embedded NULLs,
1403          * others leave them encoded, even with the same version of crypt32.
1404          * Accept either.
1405          */
1406         ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1407          got->dwValueType == CERT_RDN_IA5_STRING,
1408          "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1409          got->dwValueType);
1410         if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1411             expected = &rdnEncodedValue;
1412         else if (got->dwValueType == CERT_RDN_IA5_STRING)
1413             expected = &embeddedNullValue;
1414         if (expected)
1415         {
1416             ok(got->Value.cbData == expected->Value.cbData,
1417              "String type %d: unexpected data size, got %d, expected %d\n",
1418              got->dwValueType, got->Value.cbData, expected->Value.cbData);
1419             if (got->Value.cbData && got->Value.pbData)
1420                 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1421                  min(got->Value.cbData, expected->Value.cbData)),
1422                  "String type %d: unexpected value\n", expected->dwValueType);
1423         }
1424         LocalFree(buf);
1425     }
1426 }
1427
1428 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1429 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1430 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1431  'h','q','.','o','r','g',0 };
1432 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1433  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1434  0x6f, 0x72, 0x67 };
1435 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1436  0x575b, 0 };
1437 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1438 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1439  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1440 static const BYTE localhost[] = { 127, 0, 0, 1 };
1441 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1442  0x01 };
1443 static const unsigned char encodedCommonName[] = {
1444     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1445 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1446 static const BYTE encodedDirectoryName[] = {
1447 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1448 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1449
1450 static void test_encodeAltName(DWORD dwEncoding)
1451 {
1452     CERT_ALT_NAME_INFO info = { 0 };
1453     CERT_ALT_NAME_ENTRY entry = { 0 };
1454     BYTE *buf = NULL;
1455     DWORD size = 0;
1456     BOOL ret;
1457     char oid[] = "1.2.3";
1458
1459     /* Test with empty info */
1460     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1461      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1462     if (buf)
1463     {
1464         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1465         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1466         LocalFree(buf);
1467     }
1468     /* Test with an empty entry */
1469     info.cAltEntry = 1;
1470     info.rgAltEntry = &entry;
1471     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1472      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1473     ok(!ret && GetLastError() == E_INVALIDARG,
1474      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1475     /* Test with an empty pointer */
1476     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1477     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1478      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1479     if (buf)
1480     {
1481         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1482         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1483         LocalFree(buf);
1484     }
1485     /* Test with a real URL */
1486     U(entry).pwszURL = (LPWSTR)url;
1487     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1488      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1489     if (buf)
1490     {
1491         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1492         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1493         LocalFree(buf);
1494     }
1495     /* Now with the URL containing an invalid IA5 char */
1496     U(entry).pwszURL = (LPWSTR)nihongoURL;
1497     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1498      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1499     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1500      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1501     /* The first invalid character is at index 7 */
1502     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1503      "Expected invalid char at index 7, got %d\n",
1504      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1505     /* Now with the URL missing a scheme */
1506     U(entry).pwszURL = (LPWSTR)dnsName;
1507     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1508      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1509     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1510     if (buf)
1511     {
1512         /* This succeeds, but it shouldn't, so don't worry about conforming */
1513         LocalFree(buf);
1514     }
1515     /* Now with a DNS name */
1516     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1517     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1518      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1519     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1520     if (buf)
1521     {
1522         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1523         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1524         LocalFree(buf);
1525     }
1526     /* Test with an IP address */
1527     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1528     U(entry).IPAddress.cbData = sizeof(localhost);
1529     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1530     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1531      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1532     if (buf)
1533     {
1534         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1535         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1536         LocalFree(buf);
1537     }
1538     /* Test with OID */
1539     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1540     U(entry).pszRegisteredID = oid;
1541     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1542      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1543     if (buf)
1544     {
1545         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1546         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1547         LocalFree(buf);
1548     }
1549     /* Test with directory name */
1550     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1551     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1552     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1553     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1554      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1555     if (buf)
1556     {
1557         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1558         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1559         LocalFree(buf);
1560     }
1561 }
1562
1563 static void test_decodeAltName(DWORD dwEncoding)
1564 {
1565     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1566      0x00, 0x00, 0x01 };
1567     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1568      0x01 };
1569     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1570      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1571     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1572      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1573     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1574      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1575     BOOL ret;
1576     BYTE *buf = NULL;
1577     DWORD bufSize = 0;
1578     CERT_ALT_NAME_INFO *info;
1579
1580     /* Test some bogus ones first */
1581     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1582      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1583      NULL, &buf, &bufSize);
1584     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1585      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1586      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1587      GetLastError());
1588     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1589      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1590      &bufSize);
1591     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1592      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1593      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1594      GetLastError());
1595     /* Now expected cases */
1596     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1597      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1599     if (buf)
1600     {
1601         info = (CERT_ALT_NAME_INFO *)buf;
1602
1603         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1604          info->cAltEntry);
1605         LocalFree(buf);
1606     }
1607     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1608      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1609     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1610     if (buf)
1611     {
1612         info = (CERT_ALT_NAME_INFO *)buf;
1613
1614         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1615          info->cAltEntry);
1616         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1617          "Expected CERT_ALT_NAME_URL, got %d\n",
1618          info->rgAltEntry[0].dwAltNameChoice);
1619         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1620          "Expected empty URL\n");
1621         LocalFree(buf);
1622     }
1623     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1624      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1625     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1626     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1627      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1628     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1629     if (buf)
1630     {
1631         info = (CERT_ALT_NAME_INFO *)buf;
1632
1633         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1634          info->cAltEntry);
1635         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1636          "Expected CERT_ALT_NAME_URL, got %d\n",
1637          info->rgAltEntry[0].dwAltNameChoice);
1638         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1639         LocalFree(buf);
1640     }
1641     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1642      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1643     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1644     if (buf)
1645     {
1646         info = (CERT_ALT_NAME_INFO *)buf;
1647
1648         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1649          info->cAltEntry);
1650         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1651          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1652          info->rgAltEntry[0].dwAltNameChoice);
1653         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1654          "Unexpected DNS name\n");
1655         LocalFree(buf);
1656     }
1657     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1658      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1659     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1660     if (buf)
1661     {
1662         info = (CERT_ALT_NAME_INFO *)buf;
1663
1664         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1665          info->cAltEntry);
1666         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1667          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1668          info->rgAltEntry[0].dwAltNameChoice);
1669         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1670          "Unexpected IP address length %d\n",
1671           U(info->rgAltEntry[0]).IPAddress.cbData);
1672         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1673          sizeof(localhost)), "Unexpected IP address value\n");
1674         LocalFree(buf);
1675     }
1676     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1677      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1678     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1679     if (buf)
1680     {
1681         info = (CERT_ALT_NAME_INFO *)buf;
1682
1683         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1684          info->cAltEntry);
1685         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1686          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1687          info->rgAltEntry[0].dwAltNameChoice);
1688         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1689            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1690         LocalFree(buf);
1691     }
1692     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1693      encodedDirectoryName, sizeof(encodedDirectoryName),
1694      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1695     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1696     if (buf)
1697     {
1698         info = (CERT_ALT_NAME_INFO *)buf;
1699
1700         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1701          info->cAltEntry);
1702         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1703          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1704          info->rgAltEntry[0].dwAltNameChoice);
1705         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1706          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1707           U(info->rgAltEntry[0]).DirectoryName.cbData);
1708         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1709          encodedCommonName, sizeof(encodedCommonName)),
1710          "Unexpected directory name value\n");
1711         LocalFree(buf);
1712     }
1713     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1714      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1715      NULL, &buf, &bufSize);
1716     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1717      * particular failure, just that it doesn't decode.
1718      * It succeeds on (broken) Windows versions that haven't addressed
1719      * embedded NULLs in alternate names.
1720      */
1721     ok(!ret || broken(ret), "expected failure\n");
1722     /* An embedded bell character is allowed, however. */
1723     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1724      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1725      NULL, &buf, &bufSize);
1726     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1727     if (ret)
1728     {
1729         info = (CERT_ALT_NAME_INFO *)buf;
1730
1731         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1732          info->cAltEntry);
1733         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1734          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1735          info->rgAltEntry[0].dwAltNameChoice);
1736         LocalFree(buf);
1737     }
1738     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1739      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1740      NULL, &buf, &bufSize);
1741     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1742      * about the particular failure, just that it doesn't decode.
1743      * It succeeds on (broken) Windows versions that haven't addressed
1744      * embedded NULLs in alternate names.
1745      */
1746     ok(!ret || broken(ret), "expected failure\n");
1747 }
1748
1749 struct UnicodeExpectedError
1750 {
1751     DWORD   valueType;
1752     LPCWSTR str;
1753     DWORD   errorIndex;
1754     DWORD   error;
1755 };
1756
1757 static const WCHAR oneW[] = { '1',0 };
1758 static const WCHAR aW[] = { 'a',0 };
1759 static const WCHAR quoteW[] = { '"', 0 };
1760
1761 static struct UnicodeExpectedError unicodeErrors[] = {
1762  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1763  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1764  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1765  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1766  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1767  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1768 };
1769
1770 struct UnicodeExpectedResult
1771 {
1772     DWORD           valueType;
1773     LPCWSTR         str;
1774     CRYPT_DATA_BLOB encoded;
1775 };
1776
1777 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1778 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1779 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1780 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1781 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1782 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1783 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1784 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1785 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1786 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1787 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1788 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1789  0x5b };
1790 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1791  0x6f,0x5b };
1792 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1793  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1794 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1795  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1796
1797 static struct UnicodeExpectedResult unicodeResults[] = {
1798  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1799  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1800  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1801  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1802  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1803  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1804  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1805  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1806  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1807  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1808  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1809  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1810  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1811 };
1812
1813 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1814  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1815  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1816 };
1817
1818 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1819 {
1820     BYTE *buf = NULL;
1821     DWORD size = 0, i;
1822     BOOL ret;
1823     CERT_NAME_VALUE value;
1824
1825     if (0)
1826     {
1827         /* Crashes on win9x */
1828         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1829          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1830         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1831          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1832     }
1833     /* Have to have a string of some sort */
1834     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1835     value.Value.pbData = NULL;
1836     value.Value.cbData = 0;
1837     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1838      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1839     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1840      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1841     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1842     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1843      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1844     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1845      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1846     value.dwValueType = CERT_RDN_ANY_TYPE;
1847     value.Value.pbData = (LPBYTE)oneW;
1848     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1849      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1850     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1851      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1852     value.Value.cbData = sizeof(oneW);
1853     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1854      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1855     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1856      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1857     /* An encoded string with specified length isn't good enough either */
1858     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1859     value.Value.pbData = oneUniversal;
1860     value.Value.cbData = sizeof(oneUniversal);
1861     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1862      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1863     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1864      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1865     /* More failure checking */
1866     value.Value.cbData = 0;
1867     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1868     {
1869         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1870         value.dwValueType = unicodeErrors[i].valueType;
1871         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1872          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1873         ok(!ret && GetLastError() == unicodeErrors[i].error,
1874          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1875          unicodeErrors[i].error, GetLastError());
1876         ok(size == unicodeErrors[i].errorIndex,
1877          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1878          size);
1879     }
1880     /* cbData can be zero if the string is NULL-terminated */
1881     value.Value.cbData = 0;
1882     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1883     {
1884         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1885         value.dwValueType = unicodeResults[i].valueType;
1886         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1887          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1888         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1889          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1890         if (buf)
1891         {
1892             ok(size == unicodeResults[i].encoded.cbData,
1893              "Value type %d: expected size %d, got %d\n",
1894              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1895             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1896              "Value type %d: unexpected value\n", value.dwValueType);
1897             LocalFree(buf);
1898         }
1899     }
1900     /* These "encode," but they do so by truncating each unicode character
1901      * rather than properly encoding it.  Kept separate from the proper results,
1902      * because the encoded forms won't decode to their original strings.
1903      */
1904     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1905     {
1906         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1907         value.dwValueType = unicodeWeirdness[i].valueType;
1908         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1909          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1910         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1911         if (buf)
1912         {
1913             ok(size == unicodeWeirdness[i].encoded.cbData,
1914              "Value type %d: expected size %d, got %d\n",
1915              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1916             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1917              "Value type %d: unexpected value\n", value.dwValueType);
1918             LocalFree(buf);
1919         }
1920     }
1921 }
1922
1923 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1924 {
1925     if (n <= 0) return 0;
1926     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1927     return *str1 - *str2;
1928 }
1929
1930 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1931 {
1932     DWORD i;
1933
1934     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1935     {
1936         BYTE *buf = NULL;
1937         BOOL ret;
1938         DWORD size = 0;
1939
1940         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1941          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1942          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1943         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1944          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1945         if (ret && buf)
1946         {
1947             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1948
1949             ok(value->dwValueType == unicodeResults[i].valueType,
1950              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1951              value->dwValueType);
1952             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1953              value->Value.cbData / sizeof(WCHAR)),
1954              "Unexpected decoded value for index %d (value type %d)\n", i,
1955              unicodeResults[i].valueType);
1956             LocalFree(buf);
1957         }
1958     }
1959 }
1960
1961 struct encodedOctets
1962 {
1963     const BYTE *val;
1964     const BYTE *encoded;
1965 };
1966
1967 static const unsigned char bin46[] = { 'h','i',0 };
1968 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1969 static const unsigned char bin48[] = {
1970      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1971 static const unsigned char bin49[] = {
1972      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1973 static const unsigned char bin50[] = { 0 };
1974 static const unsigned char bin51[] = { 0x04,0x00,0 };
1975
1976 static const struct encodedOctets octets[] = {
1977     { bin46, bin47 },
1978     { bin48, bin49 },
1979     { bin50, bin51 },
1980 };
1981
1982 static void test_encodeOctets(DWORD dwEncoding)
1983 {
1984     CRYPT_DATA_BLOB blob;
1985     DWORD i;
1986
1987     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1988     {
1989         BYTE *buf = NULL;
1990         BOOL ret;
1991         DWORD bufSize = 0;
1992
1993         blob.cbData = strlen((const char*)octets[i].val);
1994         blob.pbData = (BYTE*)octets[i].val;
1995         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1996          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1997         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1998         if (buf)
1999         {
2000             ok(buf[0] == 4,
2001              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2002             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2003              buf[1], octets[i].encoded[1]);
2004             ok(!memcmp(buf + 1, octets[i].encoded + 1,
2005              octets[i].encoded[1] + 1), "Got unexpected value\n");
2006             LocalFree(buf);
2007         }
2008     }
2009 }
2010
2011 static void test_decodeOctets(DWORD dwEncoding)
2012 {
2013     DWORD i;
2014
2015     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2016     {
2017         BYTE *buf = NULL;
2018         BOOL ret;
2019         DWORD bufSize = 0;
2020
2021         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2022          octets[i].encoded, octets[i].encoded[1] + 2,
2023          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2024         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2025         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2026          "Expected size >= %d, got %d\n",
2027            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2028         ok(buf != NULL, "Expected allocated buffer\n");
2029         if (buf)
2030         {
2031             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2032
2033             if (blob->cbData)
2034                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2035                  "Unexpected value\n");
2036             LocalFree(buf);
2037         }
2038     }
2039 }
2040
2041 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2042
2043 struct encodedBits
2044 {
2045     DWORD cUnusedBits;
2046     const BYTE *encoded;
2047     DWORD cbDecoded;
2048     const BYTE *decoded;
2049 };
2050
2051 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2052 static const unsigned char bin53[] = { 0xff,0xff };
2053 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2054 static const unsigned char bin55[] = { 0xff,0xfe };
2055 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2056 static const unsigned char bin57[] = { 0xfe };
2057 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2058
2059 static const struct encodedBits bits[] = {
2060     /* normal test cases */
2061     { 0, bin52, 2, bin53 },
2062     { 1, bin54, 2, bin55 },
2063     /* strange test case, showing cUnusedBits >= 8 is allowed */
2064     { 9, bin56, 1, bin57 },
2065 };
2066
2067 static void test_encodeBits(DWORD dwEncoding)
2068 {
2069     DWORD i;
2070
2071     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2072     {
2073         CRYPT_BIT_BLOB blob;
2074         BOOL ret;
2075         BYTE *buf = NULL;
2076         DWORD bufSize = 0;
2077
2078         blob.cbData = sizeof(bytesToEncode);
2079         blob.pbData = (BYTE *)bytesToEncode;
2080         blob.cUnusedBits = bits[i].cUnusedBits;
2081         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2082          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2083         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2084         if (buf)
2085         {
2086             ok(bufSize == bits[i].encoded[1] + 2,
2087              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2088              bits[i].encoded[1] + 2);
2089             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2090              "%d: Unexpected value\n", i);
2091             LocalFree(buf);
2092         }
2093     }
2094 }
2095
2096 static void test_decodeBits(DWORD dwEncoding)
2097 {
2098     static const BYTE ber[] = "\x03\x02\x01\xff";
2099     static const BYTE berDecoded = 0xfe;
2100     DWORD i;
2101     BOOL ret;
2102     BYTE *buf = NULL;
2103     DWORD bufSize = 0;
2104
2105     /* normal cases */
2106     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2107     {
2108         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2109          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2110          &bufSize);
2111         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2112         if (buf)
2113         {
2114             CRYPT_BIT_BLOB *blob;
2115
2116             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2117                "Got unexpected size %d\n", bufSize);
2118             blob = (CRYPT_BIT_BLOB *)buf;
2119             ok(blob->cbData == bits[i].cbDecoded,
2120              "Got unexpected length %d, expected %d\n", blob->cbData,
2121              bits[i].cbDecoded);
2122             if (blob->cbData && bits[i].cbDecoded)
2123                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2124                  "Unexpected value\n");
2125             LocalFree(buf);
2126         }
2127     }
2128     /* special case: check that something that's valid in BER but not in DER
2129      * decodes successfully
2130      */
2131     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2132      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2133     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2134     if (buf)
2135     {
2136         CRYPT_BIT_BLOB *blob;
2137
2138         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2139            "Got unexpected size %d\n", bufSize);
2140         blob = (CRYPT_BIT_BLOB *)buf;
2141         ok(blob->cbData == sizeof(berDecoded),
2142            "Got unexpected length %d\n", blob->cbData);
2143         if (blob->cbData)
2144             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2145         LocalFree(buf);
2146     }
2147 }
2148
2149 struct Constraints2
2150 {
2151     CERT_BASIC_CONSTRAINTS2_INFO info;
2152     const BYTE *encoded;
2153 };
2154
2155 static const unsigned char bin59[] = { 0x30,0x00 };
2156 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2157 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2158 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2159 static const struct Constraints2 constraints2[] = {
2160  /* empty constraints */
2161  { { FALSE, FALSE, 0}, bin59 },
2162  /* can be a CA */
2163  { { TRUE,  FALSE, 0}, bin60 },
2164  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2165   * but that's not the case
2166   */
2167  { { FALSE, TRUE,  0}, bin61 },
2168  /* can be a CA and has path length constraints set */
2169  { { TRUE,  TRUE,  1}, bin62 },
2170 };
2171
2172 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2173 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2174  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2175  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2176  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2177 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2178  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2179  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2180  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2181  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2182
2183 static void test_encodeBasicConstraints(DWORD dwEncoding)
2184 {
2185     DWORD i, bufSize = 0;
2186     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2187     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2188      (LPBYTE)encodedDomainName };
2189     BOOL ret;
2190     BYTE *buf = NULL;
2191
2192     /* First test with the simpler info2 */
2193     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2194     {
2195         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2197          &bufSize);
2198         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2199         if (buf)
2200         {
2201             ok(bufSize == constraints2[i].encoded[1] + 2,
2202              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2203              bufSize);
2204             ok(!memcmp(buf, constraints2[i].encoded,
2205              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2206             LocalFree(buf);
2207         }
2208     }
2209     /* Now test with more complex basic constraints */
2210     info.SubjectType.cbData = 0;
2211     info.fPathLenConstraint = FALSE;
2212     info.cSubtreesConstraint = 0;
2213     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2214      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2215     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2216      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2217     if (buf)
2218     {
2219         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2220         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2221          "Unexpected value\n");
2222         LocalFree(buf);
2223     }
2224     /* None of the certs I examined had any subtree constraint, but I test one
2225      * anyway just in case.
2226      */
2227     info.cSubtreesConstraint = 1;
2228     info.rgSubtreesConstraint = &nameBlob;
2229     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2230      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2231     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2232      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2233     if (buf)
2234     {
2235         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2236         ok(!memcmp(buf, constraintWithDomainName,
2237          sizeof(constraintWithDomainName)), "Unexpected value\n");
2238         LocalFree(buf);
2239     }
2240     /* FIXME: test encoding with subject type. */
2241 }
2242
2243 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2244
2245 static void test_decodeBasicConstraints(DWORD dwEncoding)
2246 {
2247     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2248      0xff };
2249     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2250     DWORD i;
2251     BOOL ret;
2252     BYTE *buf = NULL;
2253     DWORD bufSize = 0;
2254
2255     /* First test with simpler info2 */
2256     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2257     {
2258         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2259          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2260          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2261         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2262          GetLastError());
2263         if (buf)
2264         {
2265             CERT_BASIC_CONSTRAINTS2_INFO *info =
2266              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2267
2268             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2269              "Unexpected value for item %d\n", i);
2270             LocalFree(buf);
2271         }
2272     }
2273     /* Check with the order of encoded elements inverted */
2274     buf = (PBYTE)1;
2275     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2276      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2277      &bufSize);
2278     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2279      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2280      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2281      GetLastError());
2282     ok(!buf, "Expected buf to be set to NULL\n");
2283     /* Check with a non-DER bool */
2284     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2285      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2286      &buf, &bufSize);
2287     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2288     if (buf)
2289     {
2290         CERT_BASIC_CONSTRAINTS2_INFO *info =
2291          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2292
2293         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2294         LocalFree(buf);
2295     }
2296     /* Check with a non-basic constraints value */
2297     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2298      encodedCommonName, encodedCommonName[1] + 2,
2299      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2300     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2301      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2302      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2303      GetLastError());
2304     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2305     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2306      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2307      &buf, &bufSize);
2308     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2309     if (buf)
2310     {
2311         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2312
2313         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2314         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2315         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2316         LocalFree(buf);
2317     }
2318     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2319      constraintWithDomainName, sizeof(constraintWithDomainName),
2320      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322     if (buf)
2323     {
2324         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2325
2326         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2327         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2328         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2329         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2330         {
2331             ok(info->rgSubtreesConstraint[0].cbData ==
2332              sizeof(encodedDomainName), "Wrong size %d\n",
2333              info->rgSubtreesConstraint[0].cbData);
2334             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2335              sizeof(encodedDomainName)), "Unexpected value\n");
2336         }
2337         LocalFree(buf);
2338     }
2339 }
2340
2341 /* These are terrible public keys of course, I'm just testing encoding */
2342 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2343 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2344 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2345 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2346 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2347 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2349 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2350
2351 struct EncodedRSAPubKey
2352 {
2353     const BYTE *modulus;
2354     size_t modulusLen;
2355     const BYTE *encoded;
2356     size_t decodedModulusLen;
2357 };
2358
2359 struct EncodedRSAPubKey rsaPubKeys[] = {
2360     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2361     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2362     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2363     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2364 };
2365
2366 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2367 {
2368     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2369     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2370     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2371     BOOL ret;
2372     BYTE *buf = NULL;
2373     DWORD bufSize = 0, i;
2374
2375     /* Try with a bogus blob type */
2376     hdr->bType = 2;
2377     hdr->bVersion = CUR_BLOB_VERSION;
2378     hdr->reserved = 0;
2379     hdr->aiKeyAlg = CALG_RSA_KEYX;
2380     rsaPubKey->magic = 0x31415352;
2381     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2382     rsaPubKey->pubexp = 65537;
2383     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2384      sizeof(modulus1));
2385
2386     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2387      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388     ok(!ret && GetLastError() == E_INVALIDARG,
2389      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2390     /* Now with a bogus reserved field */
2391     hdr->bType = PUBLICKEYBLOB;
2392     hdr->reserved = 1;
2393     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2394      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2395     if (buf)
2396     {
2397         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2398          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2399         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2400         LocalFree(buf);
2401     }
2402     /* Now with a bogus blob version */
2403     hdr->reserved = 0;
2404     hdr->bVersion = 0;
2405     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2406      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2407     if (buf)
2408     {
2409         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2410          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2411         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2412         LocalFree(buf);
2413     }
2414     /* And with a bogus alg ID */
2415     hdr->bVersion = CUR_BLOB_VERSION;
2416     hdr->aiKeyAlg = CALG_DES;
2417     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2418      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2419     if (buf)
2420     {
2421         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2422          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2423         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2424         LocalFree(buf);
2425     }
2426     /* Check a couple of RSA-related OIDs */
2427     hdr->aiKeyAlg = CALG_RSA_KEYX;
2428     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2429      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2430     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2431      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2432     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2433      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2434     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2435      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2436     /* Finally, all valid */
2437     hdr->aiKeyAlg = CALG_RSA_KEYX;
2438     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2439     {
2440         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2441          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2442         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2443          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2444         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2445         if (buf)
2446         {
2447             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2448              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2449              bufSize);
2450             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2451              "Unexpected value\n");
2452             LocalFree(buf);
2453         }
2454     }
2455 }
2456
2457 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2458 {
2459     DWORD i;
2460     LPBYTE buf = NULL;
2461     DWORD bufSize = 0;
2462     BOOL ret;
2463
2464     /* Try with a bad length */
2465     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2466      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2467      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2468     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2469      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2470      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2471      GetLastError());
2472     /* Try with a couple of RSA-related OIDs */
2473     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2474      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2475      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2476     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2477      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2478     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2479      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2480      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2481     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2482      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2483     /* Now try success cases */
2484     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2485     {
2486         bufSize = 0;
2487         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2488          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2489          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2490         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2491         if (buf)
2492         {
2493             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2494             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2495
2496             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2497              rsaPubKeys[i].decodedModulusLen,
2498              "Wrong size %d\n", bufSize);
2499             ok(hdr->bType == PUBLICKEYBLOB,
2500              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2501              hdr->bType);
2502             ok(hdr->bVersion == CUR_BLOB_VERSION,
2503              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2504              CUR_BLOB_VERSION, hdr->bVersion);
2505             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2506              hdr->reserved);
2507             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2508              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2509             ok(rsaPubKey->magic == 0x31415352,
2510              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2511             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2512              "Wrong bit len %d\n", rsaPubKey->bitlen);
2513             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2514              rsaPubKey->pubexp);
2515             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2516              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2517              "Unexpected modulus\n");
2518             LocalFree(buf);
2519         }
2520     }
2521 }
2522
2523 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2524  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2525  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2526
2527 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2528  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2529  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2530  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2531
2532 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2533 {
2534     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2535     CRYPT_SEQUENCE_OF_ANY seq;
2536     DWORD i;
2537     BOOL ret;
2538     BYTE *buf = NULL;
2539     DWORD bufSize = 0;
2540
2541     /* Encode a homogeneous sequence */
2542     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2543     {
2544         blobs[i].cbData = ints[i].encoded[1] + 2;
2545         blobs[i].pbData = (BYTE *)ints[i].encoded;
2546     }
2547     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2548     seq.rgValue = blobs;
2549
2550     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2551      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2552     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2553     if (buf)
2554     {
2555         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2556         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2557         LocalFree(buf);
2558     }
2559     /* Change the type of the first element in the sequence, and give it
2560      * another go
2561      */
2562     blobs[0].cbData = times[0].encodedTime[1] + 2;
2563     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2564     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2565      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2566     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2567     if (buf)
2568     {
2569         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2570         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2571          "Unexpected value\n");
2572         LocalFree(buf);
2573     }
2574 }
2575
2576 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2577 {
2578     BOOL ret;
2579     BYTE *buf = NULL;
2580     DWORD bufSize = 0;
2581
2582     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2583      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2584     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2585     if (buf)
2586     {
2587         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2588         DWORD i;
2589
2590         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2591          "Wrong elements %d\n", seq->cValue);
2592         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2593         {
2594             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2595              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2596              seq->rgValue[i].cbData);
2597             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2598              ints[i].encoded[1] + 2), "Unexpected value\n");
2599         }
2600         LocalFree(buf);
2601     }
2602     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2603      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2604      &bufSize);
2605     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2606     if (buf)
2607     {
2608         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2609
2610         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2611          "Wrong elements %d\n", seq->cValue);
2612         /* Just check the first element since it's all that changed */
2613         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2614          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2615          seq->rgValue[0].cbData);
2616         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2617          times[0].encodedTime[1] + 2), "Unexpected value\n");
2618         LocalFree(buf);
2619     }
2620 }
2621
2622 struct encodedExtensions
2623 {
2624     CERT_EXTENSIONS exts;
2625     const BYTE *encoded;
2626 };
2627
2628 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2629 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2630 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2631 static CERT_EXTENSION criticalExt =
2632  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2633 static CERT_EXTENSION nonCriticalExt =
2634  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2635 static CHAR oid_short[] = "1.1";
2636 static CERT_EXTENSION extWithShortOid =
2637  { oid_short, FALSE, { 0, NULL } };
2638
2639 static const BYTE ext0[] = { 0x30,0x00 };
2640 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2641                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2642 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2643                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2644 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2645
2646 static const struct encodedExtensions exts[] = {
2647  { { 0, NULL }, ext0 },
2648  { { 1, &criticalExt }, ext1 },
2649  { { 1, &nonCriticalExt }, ext2 },
2650  { { 1, &extWithShortOid }, ext3 }
2651 };
2652
2653 static void test_encodeExtensions(DWORD dwEncoding)
2654 {
2655     DWORD i;
2656
2657     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2658     {
2659         BOOL ret;
2660         BYTE *buf = NULL;
2661         DWORD bufSize = 0;
2662
2663         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2664          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2665         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2666         if (buf)
2667         {
2668             ok(bufSize == exts[i].encoded[1] + 2,
2669              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2670             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2671              "Unexpected value\n");
2672             LocalFree(buf);
2673         }
2674     }
2675 }
2676
2677 static void test_decodeExtensions(DWORD dwEncoding)
2678 {
2679     DWORD i;
2680
2681     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2682     {
2683         BOOL ret;
2684         BYTE *buf = NULL;
2685         DWORD bufSize = 0;
2686
2687         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2688          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2689          NULL, &buf, &bufSize);
2690         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2691         if (buf)
2692         {
2693             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2694             DWORD j;
2695
2696             ok(ext->cExtension == exts[i].exts.cExtension,
2697              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2698              ext->cExtension);
2699             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2700             {
2701                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2702                  exts[i].exts.rgExtension[j].pszObjId),
2703                  "Expected OID %s, got %s\n",
2704                  exts[i].exts.rgExtension[j].pszObjId,
2705                  ext->rgExtension[j].pszObjId);
2706                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2707                  exts[i].exts.rgExtension[j].Value.pbData,
2708                  exts[i].exts.rgExtension[j].Value.cbData),
2709                  "Unexpected value\n");
2710             }
2711             LocalFree(buf);
2712         }
2713     }
2714 }
2715
2716 /* MS encodes public key info with a NULL if the algorithm identifier's
2717  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2718  * it encodes them by omitting the algorithm parameters.  It accepts either
2719  * form for decoding.
2720  */
2721 struct encodedPublicKey
2722 {
2723     CERT_PUBLIC_KEY_INFO info;
2724     const BYTE *encoded;
2725     const BYTE *encodedNoNull;
2726     CERT_PUBLIC_KEY_INFO decoded;
2727 };
2728
2729 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2730  0xe, 0xf };
2731 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2732
2733 static const unsigned char bin64[] = {
2734     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2735 static const unsigned char bin65[] = {
2736     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2737 static const unsigned char bin66[] = {
2738     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2739 static const unsigned char bin67[] = {
2740     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2741 static const unsigned char bin68[] = {
2742     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2743     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2744 static const unsigned char bin69[] = {
2745     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2746     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2747 static const unsigned char bin70[] = {
2748     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2749     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2750     0x0f};
2751 static const unsigned char bin71[] = {
2752     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2753     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2754     0x0f};
2755 static unsigned char bin72[] = { 0x05,0x00};
2756
2757 static CHAR oid_bogus[] = "1.2.3",
2758             oid_rsa[]   = szOID_RSA;
2759
2760 static const struct encodedPublicKey pubKeys[] = {
2761  /* with a bogus OID */
2762  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2763   bin64, bin65,
2764   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2765  /* some normal keys */
2766  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2767   bin66, bin67,
2768   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2769  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2770   bin68, bin69,
2771   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2772  /* with add'l parameters--note they must be DER-encoded */
2773  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2774   (BYTE *)aKey, 0 } },
2775   bin70, bin71,
2776   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2777   (BYTE *)aKey, 0 } } },
2778 };
2779
2780 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2781 {
2782     DWORD i;
2783
2784     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2785     {
2786         BOOL ret;
2787         BYTE *buf = NULL;
2788         DWORD bufSize = 0;
2789
2790         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2791          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2792          &bufSize);
2793         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2794          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2795         if (buf)
2796         {
2797             ok(bufSize == pubKeys[i].encoded[1] + 2,
2798              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2799             if (bufSize == pubKeys[i].encoded[1] + 2)
2800                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2801                  "Unexpected value\n");
2802             LocalFree(buf);
2803         }
2804     }
2805 }
2806
2807 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2808  const CERT_PUBLIC_KEY_INFO *got)
2809 {
2810     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2811      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2812      got->Algorithm.pszObjId);
2813     ok(expected->Algorithm.Parameters.cbData ==
2814      got->Algorithm.Parameters.cbData,
2815      "Expected parameters of %d bytes, got %d\n",
2816      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2817     if (expected->Algorithm.Parameters.cbData)
2818         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2819          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2820          "Unexpected algorithm parameters\n");
2821     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2822      "Expected public key of %d bytes, got %d\n",
2823      expected->PublicKey.cbData, got->PublicKey.cbData);
2824     if (expected->PublicKey.cbData)
2825         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2826          got->PublicKey.cbData), "Unexpected public key value\n");
2827 }
2828
2829 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2830 {
2831     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2832      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2833      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2834      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2835     DWORD i;
2836     BOOL ret;
2837     BYTE *buf = NULL;
2838     DWORD bufSize = 0;
2839
2840     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2841     {
2842         /* The NULL form decodes to the decoded member */
2843         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2844          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2845          NULL, &buf, &bufSize);
2846         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2847         if (buf)
2848         {
2849             comparePublicKeyInfo(&pubKeys[i].decoded,
2850              (CERT_PUBLIC_KEY_INFO *)buf);
2851             LocalFree(buf);
2852         }
2853         /* The non-NULL form decodes to the original */
2854         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2855          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2856          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2857         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2858         if (buf)
2859         {
2860             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2861             LocalFree(buf);
2862         }
2863     }
2864     /* Test with bogus (not valid DER) parameters */
2865     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2866      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2867      NULL, &buf, &bufSize);
2868     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2869      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2870      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2871      GetLastError());
2872 }
2873
2874 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2875  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2876  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2877  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2878  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2879 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2880  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2881  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2882  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2883  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2884 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2885  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2886  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2887  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2888  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2889 static const BYTE v4Cert[] = {
2890 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2891 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2892 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2893 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2894 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2895  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2896  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2897  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2898  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2899  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2900  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2901 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2902  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2903  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2904  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2905  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2906  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2907  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2908 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2909  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2910  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2911  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2912  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2913  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2914  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2915  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2916  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2917  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2918 static const BYTE v1CertWithPubKey[] = {
2919 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2920 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2921 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2922 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2923 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2924 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2925 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2926 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2927 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2928 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2929 0x01,0x01 };
2930 static const BYTE v1CertWithPubKeyNoNull[] = {
2931 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2932 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2933 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2934 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2935 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2936 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2937 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2938 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2939 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2940 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2941 static const BYTE v1CertWithSubjectKeyId[] = {
2942 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2943 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2944 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2945 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2946 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2947 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2948 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2949 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2950 0x4c,0x61,0x6e,0x67,0x00 };
2951 static const BYTE v1CertWithIssuerUniqueId[] = {
2952 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2953 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2954 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2955 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2956 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2957 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2958 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2959 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2960 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2961 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2962 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2963 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2964 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2965 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2966 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2967 0x01,0x01,0xff,0x02,0x01,0x01 };
2968 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2969 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2970 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2971 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2972 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2973 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2974 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2975 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2976 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2977 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2978 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2979 0xff,0x02,0x01,0x01 };
2980
2981 static const BYTE serialNum[] = { 0x01 };
2982
2983 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2984 {
2985     BOOL ret;
2986     BYTE *buf = NULL;
2987     DWORD size = 0;
2988     CERT_INFO info = { 0 };
2989     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2990     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2991     CERT_EXTENSION ext;
2992
2993     if (0)
2994     {
2995         /* Test with NULL pvStructInfo (crashes on win9x) */
2996         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2997          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2998         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2999          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3000     }
3001     /* Test with a V1 cert */
3002     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3003      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3004     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3005      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3006     if (buf)
3007     {
3008         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3009          v1Cert[1] + 2, size);
3010         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3011         LocalFree(buf);
3012     }
3013     /* Test v2 cert */
3014     info.dwVersion = CERT_V2;
3015     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3016      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3017     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3018      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3019     if (buf)
3020     {
3021         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3022         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3023         LocalFree(buf);
3024     }
3025     /* Test v3 cert */
3026     info.dwVersion = CERT_V3;
3027     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3028      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3029     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3030      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3031     if (buf)
3032     {
3033         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3034         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3035         LocalFree(buf);
3036     }
3037     /* A v4 cert? */
3038     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3039     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3040      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3041     if (buf)
3042     {
3043         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3044         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3045         LocalFree(buf);
3046     }
3047     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3048      * API doesn't prevent it)
3049      */
3050     info.dwVersion = CERT_V1;
3051     info.cExtension = 1;
3052     info.rgExtension = &criticalExt;
3053     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3054      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3055     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3056      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3057     if (buf)
3058     {
3059         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3060         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3061         LocalFree(buf);
3062     }
3063     /* test v1 cert with a serial number */
3064     info.SerialNumber.cbData = sizeof(serialNum);
3065     info.SerialNumber.pbData = (BYTE *)serialNum;
3066     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3067      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3068     if (buf)
3069     {
3070         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3071         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3072         LocalFree(buf);
3073     }
3074     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3075     info.dwVersion = CERT_V1;
3076     info.cExtension = 0;
3077     info.IssuerUniqueId.cbData = sizeof(serialNum);
3078     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3079     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3080      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3081     ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3082      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3083     if (buf)
3084     {
3085         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3086         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3087          "Got unexpected value\n");
3088         LocalFree(buf);
3089     }
3090     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3091     info.IssuerUniqueId.cbData = 0;
3092     info.IssuerUniqueId.pbData = NULL;
3093     info.cExtension = 1;
3094     info.rgExtension = &criticalExt;
3095     info.Issuer.cbData = sizeof(encodedCommonName);
3096     info.Issuer.pbData = (BYTE *)encodedCommonName;
3097     info.Subject.cbData = sizeof(encodedCommonName);
3098     info.Subject.pbData = (BYTE *)encodedCommonName;
3099     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3100      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3101     if (buf)
3102     {
3103         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3104         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3105         LocalFree(buf);
3106     }
3107     /* Add a public key */
3108     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3109     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3110     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3111     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3112      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3113     if (buf)
3114     {
3115         ok(size == sizeof(v1CertWithPubKey) ||
3116          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3117         if (size == sizeof(v1CertWithPubKey))
3118             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3119         else if (size == sizeof(v1CertWithPubKeyNoNull))
3120             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3121              "Got unexpected value\n");
3122         LocalFree(buf);
3123     }
3124     /* Again add an issuer unique id */
3125     info.IssuerUniqueId.cbData = sizeof(serialNum);
3126     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3127     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3128      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3129     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3130     if (buf)
3131     {
3132         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3133          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3134          "Wrong size %d\n", size);
3135         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3136             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3137              size), "unexpected value\n");
3138         else if (size ==
3139          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3140             ok(!memcmp(buf,
3141              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3142              "unexpected value\n");
3143         LocalFree(buf);
3144     }
3145     /* Remove the public key, and add a subject key identifier extension */
3146     info.IssuerUniqueId.cbData = 0;
3147     info.IssuerUniqueId.pbData = NULL;
3148     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3149     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3150     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3151     ext.pszObjId = oid_subject_key_identifier;
3152     ext.fCritical = FALSE;
3153     ext.Value.cbData = sizeof(octetCommonNameValue);
3154     ext.Value.pbData = octetCommonNameValue;
3155     info.cExtension = 1;
3156     info.rgExtension = &ext;
3157     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3158      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3159     if (buf)
3160     {
3161         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3162         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3163         LocalFree(buf);
3164     }
3165 }
3166
3167 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3168 {
3169     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3170      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3171     BOOL ret;
3172     BYTE *buf = NULL;
3173     DWORD size = 0, i;
3174
3175     /* Test with NULL pbEncoded */
3176     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3177      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3178     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3179      GetLastError() == OSS_BAD_ARG /* Win9x */),
3180      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3181     if (0)
3182     {
3183         /* Crashes on win9x */
3184         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3185          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3186         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3187          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3188     }
3189     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3190      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3191      * serial number, an issuer, a subject, and a public key.
3192      */
3193     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3194     {
3195         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3196          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3197          &buf, &size);
3198         ok(!ret, "Expected failure\n");
3199     }
3200     /* The following succeeds, even though v1 certs are not allowed to have
3201      * extensions.
3202      */
3203     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3204      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3205      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3206     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3207     if (ret)
3208     {
3209         CERT_INFO *info = (CERT_INFO *)buf;
3210
3211         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3212         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3213          info->dwVersion);
3214         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3215          info->cExtension);
3216         LocalFree(buf);
3217     }
3218     /* The following also succeeds, even though V1 certs are not allowed to
3219      * have issuer unique ids.
3220      */
3221     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3222      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3223      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3224      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3225     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3226     if (ret)
3227     {
3228         CERT_INFO *info = (CERT_INFO *)buf;
3229
3230         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3231         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3232          info->dwVersion);
3233         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3234          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3235         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3236          "unexpected issuer unique id value\n");
3237         LocalFree(buf);
3238     }
3239     /* Now check with serial number, subject and issuer specified */
3240     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3241      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3242     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3243     if (buf)
3244     {
3245         CERT_INFO *info = (CERT_INFO *)buf;
3246
3247         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3248         ok(info->SerialNumber.cbData == 1,
3249          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3250         ok(*info->SerialNumber.pbData == *serialNum,
3251          "Expected serial number %d, got %d\n", *serialNum,
3252          *info->SerialNumber.pbData);
3253         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3254          "Wrong size %d\n", info->Issuer.cbData);
3255         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3256          "Unexpected issuer\n");
3257         ok(info->Subject.cbData == sizeof(encodedCommonName),
3258          "Wrong size %d\n", info->Subject.cbData);
3259         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3260          info->Subject.cbData), "Unexpected subject\n");
3261         LocalFree(buf);
3262     }
3263     /* Check again with pub key specified */
3264     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3265      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3266      &buf, &size);
3267     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3268     if (buf)
3269     {
3270         CERT_INFO *info = (CERT_INFO *)buf;
3271
3272         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3273         ok(info->SerialNumber.cbData == 1,
3274          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3275         ok(*info->SerialNumber.pbData == *serialNum,
3276          "Expected serial number %d, got %d\n", *serialNum,
3277          *info->SerialNumber.pbData);
3278         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3279          "Wrong size %d\n", info->Issuer.cbData);
3280         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3281          "Unexpected issuer\n");
3282         ok(info->Subject.cbData == sizeof(encodedCommonName),
3283          "Wrong size %d\n", info->Subject.cbData);
3284         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3285          info->Subject.cbData), "Unexpected subject\n");
3286         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3287          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3288          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3289         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3290          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3291         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3292          sizeof(aKey)), "Unexpected public key\n");
3293         LocalFree(buf);
3294     }
3295 }
3296
3297 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3298  0xe, 0xf };
3299
3300 static const BYTE signedBigCert[] = {
3301  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3302  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3303  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3304  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3305  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3306  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3307  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3308  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3309  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3310  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3311  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3312  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3313
3314 static void test_encodeCert(DWORD dwEncoding)
3315 {
3316     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3317      * also that bigCert is a NULL-terminated string, so don't count its
3318      * last byte (otherwise the signed cert won't decode.)
3319      */
3320     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3321      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3322     BOOL ret;
3323     BYTE *buf = NULL;
3324     DWORD bufSize = 0;
3325
3326     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3327      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3328     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3329     if (buf)
3330     {
3331         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3332         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3333         LocalFree(buf);
3334     }
3335 }
3336
3337 static void test_decodeCert(DWORD dwEncoding)
3338 {
3339     BOOL ret;
3340     BYTE *buf = NULL;
3341     DWORD size = 0;
3342
3343     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3344      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3345     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3346     if (buf)
3347     {
3348         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3349
3350         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3351          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3352         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3353          "Unexpected cert\n");
3354         ok(info->Signature.cbData == sizeof(hash),
3355          "Wrong signature size %d\n", info->Signature.cbData);
3356         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3357          "Unexpected signature\n");
3358         LocalFree(buf);
3359     }
3360     /* A signed cert decodes as a CERT_INFO too */
3361     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3362      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3363     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3364     if (buf)
3365     {
3366         CERT_INFO *info = (CERT_INFO *)buf;
3367
3368         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3369         ok(info->SerialNumber.cbData == 1,
3370          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3371         ok(*info->SerialNumber.pbData == *serialNum,
3372          "Expected serial number %d, got %d\n", *serialNum,
3373          *info->SerialNumber.pbData);
3374         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3375          "Wrong size %d\n", info->Issuer.cbData);
3376         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3377          "Unexpected issuer\n");
3378         ok(info->Subject.cbData == sizeof(encodedCommonName),
3379          "Wrong size %d\n", info->Subject.cbData);
3380         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3381          info->Subject.cbData), "Unexpected subject\n");
3382         LocalFree(buf);
3383     }
3384 }
3385
3386 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3387 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3388  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3389  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3390 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3391  0x00, 0x03 };
3392 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3393  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3394  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3395 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3396  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3397  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3398  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3399  0x2e, 0x6f, 0x72, 0x67 };
3400 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3401  CRL_REASON_AFFILIATION_CHANGED;
3402
3403 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3404 {
3405     CRL_DIST_POINTS_INFO info = { 0 };
3406     CRL_DIST_POINT point = { { 0 } };
3407     CERT_ALT_NAME_ENTRY entry = { 0 };
3408     BOOL ret;
3409     BYTE *buf = NULL;
3410     DWORD size = 0;
3411
3412     /* Test with an empty info */
3413     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3414      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3415     ok(!ret && GetLastError() == E_INVALIDARG,
3416      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3417     /* Test with one empty dist point */
3418     info.cDistPoint = 1;
3419     info.rgDistPoint = &point;
3420     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3421      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3422     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3423     if (buf)
3424     {
3425         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3426         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3427         LocalFree(buf);
3428     }
3429     /* A dist point with an invalid name */
3430     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3431     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3432     U(entry).pwszURL = (LPWSTR)nihongoURL;
3433     U(point.DistPointName).FullName.cAltEntry = 1;
3434     U(point.DistPointName).FullName.rgAltEntry = &entry;
3435     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3436      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3437     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3438      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3439     /* The first invalid character is at index 7 */
3440     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3441      "Expected invalid char at index 7, got %d\n",
3442      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3443     /* A dist point with (just) a valid name */
3444     U(entry).pwszURL = (LPWSTR)url;
3445     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3446      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3447     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3448     if (buf)
3449     {
3450         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3451         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3452         LocalFree(buf);
3453     }
3454     /* A dist point with (just) reason flags */
3455     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3456     point.ReasonFlags.cbData = sizeof(crlReason);
3457     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3458     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3459      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3460     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3461     if (buf)
3462     {
3463         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3464         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3465         LocalFree(buf);
3466     }
3467     /* A dist point with just an issuer */
3468     point.ReasonFlags.cbData = 0;
3469     point.CRLIssuer.cAltEntry = 1;
3470     point.CRLIssuer.rgAltEntry = &entry;
3471     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3472      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3473     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3474     if (buf)
3475     {
3476         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3477         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3478         LocalFree(buf);
3479     }
3480     /* A dist point with both a name and an issuer */
3481     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3482     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3483      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3484     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3485     if (buf)
3486     {
3487         ok(size == sizeof(distPointWithUrlAndIssuer),
3488          "Wrong size %d\n", size);
3489         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3490         LocalFree(buf);
3491     }
3492 }
3493
3494 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3495 {
3496     BOOL ret;
3497     BYTE *buf = NULL;
3498     DWORD size = 0;
3499     PCRL_DIST_POINTS_INFO info;
3500     PCRL_DIST_POINT point;
3501     PCERT_ALT_NAME_ENTRY entry;
3502
3503     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3504      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3505      &buf, &size);
3506     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3507     if (ret)
3508     {
3509         info = (PCRL_DIST_POINTS_INFO)buf;
3510         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3511          "Wrong size %d\n", size);
3512         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3513          info->cDistPoint);
3514         point = info->rgDistPoint;
3515         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3516          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3517          point->DistPointName.dwDistPointNameChoice);
3518         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3519         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3520         LocalFree(buf);
3521     }
3522     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3523      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3524      &buf, &size);
3525     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3526     if (ret)
3527     {
3528         info = (PCRL_DIST_POINTS_INFO)buf;
3529         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3530          "Wrong size %d\n", size);
3531         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3532          info->cDistPoint);
3533         point = info->rgDistPoint;
3534         ok(point->DistPointName.dwDistPointNameChoice ==
3535          CRL_DIST_POINT_FULL_NAME,
3536          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3537          point->DistPointName.dwDistPointNameChoice);
3538         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3539          "Expected 1 name entry, got %d\n",
3540          U(point->DistPointName).FullName.cAltEntry);
3541         entry = U(point->DistPointName).FullName.rgAltEntry;
3542         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3543          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3544         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3545         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3546         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3547         LocalFree(buf);
3548     }
3549     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3550      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3551      NULL, &buf, &size);
3552     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3553     if (ret)
3554     {
3555         info = (PCRL_DIST_POINTS_INFO)buf;
3556         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3557          "Wrong size %d\n", size);
3558         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3559          info->cDistPoint);
3560         point = info->rgDistPoint;
3561         ok(point->DistPointName.dwDistPointNameChoice ==
3562          CRL_DIST_POINT_NO_NAME,
3563          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3564          point->DistPointName.dwDistPointNameChoice);
3565         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3566          "Expected reason length\n");
3567         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3568          "Unexpected reason\n");
3569         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3570         LocalFree(buf);
3571     }
3572     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3573      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3574      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3575     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3576     if (ret)
3577     {
3578         info = (PCRL_DIST_POINTS_INFO)buf;
3579         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3580          "Wrong size %d\n", size);
3581         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3582          info->cDistPoint);
3583         point = info->rgDistPoint;
3584         ok(point->DistPointName.dwDistPointNameChoice ==
3585          CRL_DIST_POINT_FULL_NAME,
3586          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3587          point->DistPointName.dwDistPointNameChoice);
3588         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3589          "Expected 1 name entry, got %d\n",
3590          U(point->DistPointName).FullName.cAltEntry);
3591         entry = U(point->DistPointName).FullName.rgAltEntry;
3592         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3593          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3594         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3595         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3596         ok(point->CRLIssuer.cAltEntry == 1,
3597          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3598         entry = point->CRLIssuer.rgAltEntry;
3599         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3600          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3601         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3602         LocalFree(buf);
3603     }
3604 }
3605
3606 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3607 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3608 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3609  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3610  0x67 };
3611
3612 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3613 {
3614     BOOL ret;
3615     BYTE *buf = NULL;
3616     DWORD size = 0;
3617     CRL_ISSUING_DIST_POINT point = { { 0 } };
3618     CERT_ALT_NAME_ENTRY entry;
3619
3620     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3621      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3622     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3623     {
3624         skip("no X509_ISSUING_DIST_POINT encode support\n");
3625         return;
3626     }
3627     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3628      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3629     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3630      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3631     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3632     if (buf)
3633     {
3634         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3635         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3636         LocalFree(buf);
3637     }
3638     /* nonsensical flags */
3639     point.fOnlyContainsUserCerts = TRUE;
3640     point.fOnlyContainsCACerts = TRUE;
3641     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3642      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3643     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3644     if (buf)
3645     {
3646         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3647         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3648         LocalFree(buf);
3649     }
3650     /* unimplemented name type */
3651     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3652     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3653     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3654      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655     ok(!ret && GetLastError() == E_INVALIDARG,
3656      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3657     /* empty name */
3658     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3659     U(point.DistPointName).FullName.cAltEntry = 0;
3660     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3661      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3662     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3663     if (buf)
3664     {
3665         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3666         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3667         LocalFree(buf);
3668     }
3669     /* name with URL entry */
3670     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3671     U(entry).pwszURL = (LPWSTR)url;
3672     U(point.DistPointName).FullName.cAltEntry = 1;
3673     U(point.DistPointName).FullName.rgAltEntry = &entry;
3674     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3675      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3676     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3677     if (buf)
3678     {
3679         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3680         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3681         LocalFree(buf);
3682     }
3683 }
3684
3685 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3686  const CERT_ALT_NAME_ENTRY *got)
3687 {
3688     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3689      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3690      got->dwAltNameChoice);
3691     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3692     {
3693         switch (got->dwAltNameChoice)
3694         {
3695         case CERT_ALT_NAME_RFC822_NAME:
3696         case CERT_ALT_NAME_DNS_NAME:
3697         case CERT_ALT_NAME_EDI_PARTY_NAME:
3698         case CERT_ALT_NAME_URL:
3699         case CERT_ALT_NAME_REGISTERED_ID:
3700             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3701              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3702              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3703              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3704              "Unexpected name\n");
3705             break;
3706         case CERT_ALT_NAME_X400_ADDRESS:
3707         case CERT_ALT_NAME_DIRECTORY_NAME:
3708         case CERT_ALT_NAME_IP_ADDRESS:
3709             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3710                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3711             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3712                        U(*got).IPAddress.cbData), "Unexpected value\n");
3713             break;
3714         }
3715     }
3716 }
3717
3718 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3719  const CERT_ALT_NAME_INFO *got)
3720 {
3721     DWORD i;
3722
3723     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3724      expected->cAltEntry, got->cAltEntry);
3725     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3726         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3727 }
3728
3729 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3730  const CRL_DIST_POINT_NAME *got)
3731 {
3732     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3733      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3734     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3735         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3736 }
3737
3738 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3739  const CRL_ISSUING_DIST_POINT *got)
3740 {
3741     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3742     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3743      "Unexpected fOnlyContainsUserCerts\n");
3744     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3745      "Unexpected fOnlyContainsCACerts\n");
3746     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3747      "Unexpected reason flags\n");
3748     ok(got->fIndirectCRL == expected->fIndirectCRL,
3749      "Unexpected fIndirectCRL\n");
3750 }
3751
3752 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3753 {
3754     BOOL ret;
3755     BYTE *buf = NULL;
3756     DWORD size = 0;
3757     CRL_ISSUING_DIST_POINT point = { { 0 } };
3758
3759     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3760      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3761      &buf, &size);
3762     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3763     {
3764         skip("no X509_ISSUING_DIST_POINT decode support\n");
3765         return;
3766     }
3767     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3768     if (ret)
3769     {
3770         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3771         LocalFree(buf);
3772     }
3773     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3774      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3775      &buf, &size);
3776     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3777     if (ret)
3778     {
3779         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3780         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3781         LocalFree(buf);
3782     }
3783     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3784      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3785      &buf, &size);
3786     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3787     if (ret)
3788     {
3789         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3790         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3791         U(point.DistPointName).FullName.cAltEntry = 0;
3792         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3793         LocalFree(buf);
3794     }
3795     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3796      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3797     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3798     if (ret)
3799     {
3800         CERT_ALT_NAME_ENTRY entry;
3801
3802         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3803         U(entry).pwszURL = (LPWSTR)url;
3804         U(point.DistPointName).FullName.cAltEntry = 1;
3805         U(point.DistPointName).FullName.rgAltEntry = &entry;
3806         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3807         LocalFree(buf);
3808     }
3809 }
3810
3811 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3812  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3813  0x30, 0x5a };
3814 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3815  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3816  0x30, 0x30, 0x30, 0x30, 0x5a };
3817 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3818  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3819  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3820  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3821  0x5a };
3822 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3823  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3824  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3825  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3826  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3827  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3828 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3829  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3830  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3831  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3832  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3833  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3834 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3835  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3836  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3837  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3838  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3839  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3840  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3841 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3842  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3843  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3844  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3845  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3846  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3847  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3848 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3849  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3850  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3851  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3852  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3853  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3854  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3855
3856 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3857 {
3858     BOOL ret;
3859     BYTE *buf = NULL;
3860     DWORD size = 0;
3861     CRL_INFO info = { 0 };
3862     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3863
3864     /* Test with a V1 CRL */
3865     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3866      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3867     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3868      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3869     if (buf)
3870     {
3871         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3872         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3873         LocalFree(buf);
3874     }
3875     /* Test v2 CRL */
3876     info.dwVersion = CRL_V2;
3877     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3878      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3879     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3880      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3881     if (buf)
3882     {
3883         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3884          v2CRL[1] + 2, size);
3885         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3886         LocalFree(buf);
3887     }
3888     /* v1 CRL with a name */
3889     info.dwVersion = CRL_V1;
3890     info.Issuer.cbData = sizeof(encodedCommonName);
3891     info.Issuer.pbData = (BYTE *)encodedCommonName;
3892     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3893      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3894     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3895     if (buf)
3896     {
3897         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3898         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3899         LocalFree(buf);
3900     }
3901     if (0)
3902     {
3903         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3904         info.cCRLEntry = 1;
3905         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3906          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3907         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3908          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3909     }
3910     /* now set an empty entry */
3911     info.cCRLEntry = 1;
3912     info.rgCRLEntry = &entry;
3913     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3914      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3915     if (buf)
3916     {
3917         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3918          "Wrong size %d\n", size);
3919         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3920          "Got unexpected value\n");
3921         LocalFree(buf);
3922     }
3923     /* an entry with a serial number */
3924     entry.SerialNumber.cbData = sizeof(serialNum);
3925     entry.SerialNumber.pbData = (BYTE *)serialNum;
3926     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3927      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3928     if (buf)
3929     {
3930         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3931          "Wrong size %d\n", size);
3932         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3933          "Got unexpected value\n");
3934         LocalFree(buf);
3935     }
3936     /* an entry with an extension */
3937     entry.cExtension = 1;
3938     entry.rgExtension = &criticalExt;
3939     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3940      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3941     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3942     if (buf)
3943     {
3944         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3945         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3946         LocalFree(buf);
3947     }
3948     /* a CRL with an extension */
3949     entry.cExtension = 0;
3950     info.cExtension = 1;
3951     info.rgExtension = &criticalExt;
3952     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3953      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3954     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3955     if (buf)
3956     {
3957         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3958         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3959         LocalFree(buf);
3960     }
3961     /* a v2 CRL with an extension, this time non-critical */
3962     info.dwVersion = CRL_V2;
3963     info.rgExtension = &nonCriticalExt;
3964     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3965      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3966     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3967     if (buf)
3968     {
3969         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3970         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3971         LocalFree(buf);
3972     }
3973 }
3974
3975 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3976  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3977  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3978  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3979  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3980  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3981  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3982  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3983  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3984  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3985  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3986  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3987  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3988  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3989  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3990  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3991  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3992  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3993  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3994  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3995  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3996  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3997  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3998  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3999  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4000  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4001  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4002  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4003  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4004  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4005  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4006  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4007  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4008  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4009  0xcd };
4010 static const BYTE verisignCRLWithLotsOfEntries[] = {
4011 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4012 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4013 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4014 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4015 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4016 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4017 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4018 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4019 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4020 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4021 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4022 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4023 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4024 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4025 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4026 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4027 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4028 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4029 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4030 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4031 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4032 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4033 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4034 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4035 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4036 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4037 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4038 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4039 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4040 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4041 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4042 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4043 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4044 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4045 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4046 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4047 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4048 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4049 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4050 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4051 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4052 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4053 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4054 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4055 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4056 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4057 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4058 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4059 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4060 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4061 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4062 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4063 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4064 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4065 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4066 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4067 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4068 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4069 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4070 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4071 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4072 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4073 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4074 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4075 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4076 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4077 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4078 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4079 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4080 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4081 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4082 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4083 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4084 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4085 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4086 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4087 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4088 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4089 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4090 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4091 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4092 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4093 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4094 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4095 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4096 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4097 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4098 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4099 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4100 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4101 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4102 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4103 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4104 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4105 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4106 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4107 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4108 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4109 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4110 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4111 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4112 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4113 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4114 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4115 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4116 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4117 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4118 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4119 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4120 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4121 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4122 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4123 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4124 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4125 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4126 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4127 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4128 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4129 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4130 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4131 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4132 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4133 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4134 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4135 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4136 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4137 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4138 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4139 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4140 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4141 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4142 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4143 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4144 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4145 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4146 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4147 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4148 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4149 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4150 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4151 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4152 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4153 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4154 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4155 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4156 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4157 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4158 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4159 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4160 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4161 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4162 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4163 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4164 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4165 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4166 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4167 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4168 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4169 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4170 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4171 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4172 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4173 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4174 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4175 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4176 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4177 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4178 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4179 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4180 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4181 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4182 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4183 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4184 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4185 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4186 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4187 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4188 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4189 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4190 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4191 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4192 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4193 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4194 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4195 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4196 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4197 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4198 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4199 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4200 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4201 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4202 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4203 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4204 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4205 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4206 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4207 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4208 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4209 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4210 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4211 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4212 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4213 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4214 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4215 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4216 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4217 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4218 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4219 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4220 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4221 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4222 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4223 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4224 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4225 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4226 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4227 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4228 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4229 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4230 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4231 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4232 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4233 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4234 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4235 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4236 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4237 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4238 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4239 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4240 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4241 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4242 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4243 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4244 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4245 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4246 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4247 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4248 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4249 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4250 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4251 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4252 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4253 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4254 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4255 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4256 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4257 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4258 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4259 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4260 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4261 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4262 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4263 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4264 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4265 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4266 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4267 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4268 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4269 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4270 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4271 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4272 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4273 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4274 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4275 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4276 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4277 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4278 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4279 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4280 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4281 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4282 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4283 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4284 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4285 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4286 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4287 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4288 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4289 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4290 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4291 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4292 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4293 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4294 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4295 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4296 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4297 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4298 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4299 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4300 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4301 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4302 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4303 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4304 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4305 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4306 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4307 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4308 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4309 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4310 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4311 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4312 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4313 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4314 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4315 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4316 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4317 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4318 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4319 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4320 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4321 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4322 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4323 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4324 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4325 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4326 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4327 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4328 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4329 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4330 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4331 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4332 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4333 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4334 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4335 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4336 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4337 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4338 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4339 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4340 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4341 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4342 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4343 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4344 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4345 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4346 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4347 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4348 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4349 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4350 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4351 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4352 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4353 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4354 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4355 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4356 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4357 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4358 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4359 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4360 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4361 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4362 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4363 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4364 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4365 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4366 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4367 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4368 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4369 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4370 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4371 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4372 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4373 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4374 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4375 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4376 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4377 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4378 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4379 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4380 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4381 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4382 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4383 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4384 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4385 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4386 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4387 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4388 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4389 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4390 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4391 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4392 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4393 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4394 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4395 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4396 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4397 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4398 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4399 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4400 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4401 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4402 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4403 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4404 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4405 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4406 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4407 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4408 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4409 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4410 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4411 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4412 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4413 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4414 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4415 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4416 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4417 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4418 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4419 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4420 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4421 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4422 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4423 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4424 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4425 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4426 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4427 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4428 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4429 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4430 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4431 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4432 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4433 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4434 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4435 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4436 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4437 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4438 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4439 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4440 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4441 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4442 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4443 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4444 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4445 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4446 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4447 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4448 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4449 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4450 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4451 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4452 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4453 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4454 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4455 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4456 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4457 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4458 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4459 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4460 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4461 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4462 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4463 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4464 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4465 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4466 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4467 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4468 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4469 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4470 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4471 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4472 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4473 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4474 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4475 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4476 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4477 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4478 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4479 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4480 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4481 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4482 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4483 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4484 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4485 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4486 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4487 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4488 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4489 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4490 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4491 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4492 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4493 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4494 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4495 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4496 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4497 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4498 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4499 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4500 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4501 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4502 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4503 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4504 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4505 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4506 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4507 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4508 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4509 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4510 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4511 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4512 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4513 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4514 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4515 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4516 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4517 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4518 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4519
4520 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4521 {
4522     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4523     BOOL ret;
4524     BYTE *buf = NULL;
4525     DWORD size = 0, i;
4526
4527     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4528     {
4529         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4530          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4531          &buf, &size);
4532         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4533          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4534          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4535          GetLastError());
4536     }
4537     /* at a minimum, a CRL must contain an issuer: */
4538     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4539      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4540      &buf, &size);
4541     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4542     if (buf)
4543     {
4544         CRL_INFO *info = (CRL_INFO *)buf;
4545
4546         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4547         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4548          info->cCRLEntry);
4549         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4550          "Wrong issuer size %d\n", info->Issuer.cbData);
4551         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4552          "Unexpected issuer\n");
4553         LocalFree(buf);
4554     }
4555     /* check decoding with an empty CRL entry */
4556     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4557      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4558      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4559     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4560      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4561      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4562      GetLastError());
4563     /* with a real CRL entry */
4564     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4565      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4566      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4567     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4568     if (buf)
4569     {
4570         CRL_INFO *info = (CRL_INFO *)buf;
4571         CRL_ENTRY *entry;
4572
4573         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4574         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4575          info->cCRLEntry);
4576         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4577         entry = info->rgCRLEntry;
4578         ok(entry->SerialNumber.cbData == 1,
4579          "Expected serial number size 1, got %d\n",
4580          entry->SerialNumber.cbData);
4581         ok(*entry->SerialNumber.pbData == *serialNum,
4582          "Expected serial number %d, got %d\n", *serialNum,
4583          *entry->SerialNumber.pbData);
4584         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4585          "Wrong issuer size %d\n", info->Issuer.cbData);
4586         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4587          "Unexpected issuer\n");
4588         LocalFree(buf);
4589     }
4590     /* a real CRL from verisign that has extensions */
4591     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4592      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4593      NULL, &buf, &size);
4594     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4595     if (buf)
4596     {
4597         CRL_INFO *info = (CRL_INFO *)buf;
4598
4599         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4600         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4601          info->cCRLEntry);
4602         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4603         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4604          info->cExtension);
4605         LocalFree(buf);
4606     }
4607     /* another real CRL from verisign that has lots of entries */
4608     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4609      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4610      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4611     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4612     if (buf)
4613     {
4614         CRL_INFO *info = (CRL_INFO *)buf;
4615
4616         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4617         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4618          info->cCRLEntry);
4619         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4620          info->cExtension);
4621         LocalFree(buf);
4622     }
4623     /* and finally, with an extension */
4624     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4625      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4626      NULL, &buf, &size);
4627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4628     if (buf)
4629     {
4630         CRL_INFO *info = (CRL_INFO *)buf;
4631         CRL_ENTRY *entry;
4632
4633         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4634         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4635          info->cCRLEntry);
4636         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4637         entry = info->rgCRLEntry;
4638         ok(entry->SerialNumber.cbData == 1,
4639          "Expected serial number size 1, got %d\n",
4640          entry->SerialNumber.cbData);
4641         ok(*entry->SerialNumber.pbData == *serialNum,
4642          "Expected serial number %d, got %d\n", *serialNum,
4643          *entry->SerialNumber.pbData);
4644         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4645          "Wrong issuer size %d\n", info->Issuer.cbData);
4646         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4647          "Unexpected issuer\n");
4648         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4649          info->cExtension);
4650         LocalFree(buf);
4651     }
4652     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4653      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4654      NULL, &buf, &size);
4655     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4656     if (buf)
4657     {
4658         CRL_INFO *info = (CRL_INFO *)buf;
4659
4660         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4661          info->cExtension);
4662         LocalFree(buf);
4663     }
4664 }
4665
4666 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4667  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4668 static const BYTE encodedUsage[] = {
4669  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4670  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4671  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4672
4673 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4674 {
4675     BOOL ret;
4676     BYTE *buf = NULL;
4677     DWORD size = 0;
4678     CERT_ENHKEY_USAGE usage;
4679
4680     /* Test with empty usage */
4681     usage.cUsageIdentifier = 0;
4682     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4683      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4684     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4685     if (buf)
4686     {
4687         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4688         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4689         LocalFree(buf);
4690     }
4691     /* Test with a few usages */
4692     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4693     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4694     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4695      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4696     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4697     if (buf)
4698     {
4699         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4700         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4701         LocalFree(buf);
4702     }
4703 }
4704
4705 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4706 {
4707     BOOL ret;
4708     LPBYTE buf = NULL;
4709     DWORD size = 0;
4710
4711     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4712      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4713      &buf, &size);
4714     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4715     if (buf)
4716     {
4717         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4718
4719         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4720          "Wrong size %d\n", size);
4721         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4722          usage->cUsageIdentifier);
4723         LocalFree(buf);
4724     }
4725     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4726      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4727      &buf, &size);
4728     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4729     if (buf)
4730     {
4731         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4732         DWORD i;
4733
4734         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4735          "Wrong size %d\n", size);
4736         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4737          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4738         for (i = 0; i < usage->cUsageIdentifier; i++)
4739             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4740              "Expected OID %s, got %s\n", keyUsages[i],
4741              usage->rgpszUsageIdentifier[i]);
4742         LocalFree(buf);
4743     }
4744 }
4745
4746 static BYTE keyId[] = { 1,2,3,4 };
4747 static const BYTE authorityKeyIdWithId[] = {
4748  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4749 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4750  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4751  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4752 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4753
4754 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4755 {
4756     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4757     BOOL ret;
4758     BYTE *buf = NULL;
4759     DWORD size = 0;
4760
4761     /* Test with empty id */
4762     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4763      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4764     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4765     if (buf)
4766     {
4767         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4768         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4769         LocalFree(buf);
4770     }
4771     /* With just a key id */
4772     info.KeyId.cbData = sizeof(keyId);
4773     info.KeyId.pbData = keyId;
4774     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4775      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4776     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4777     if (buf)
4778     {
4779         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4780         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4781         LocalFree(buf);
4782     }
4783     /* With just an issuer */
4784     info.KeyId.cbData = 0;
4785     info.CertIssuer.cbData = sizeof(encodedCommonName);
4786     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4787     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4788      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4789     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4790     if (buf)
4791     {
4792         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4793          size);
4794         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4795         LocalFree(buf);
4796     }
4797     /* With just a serial number */
4798     info.CertIssuer.cbData = 0;
4799     info.CertSerialNumber.cbData = sizeof(serialNum);
4800     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4801     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4802      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4803     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4804     if (buf)
4805     {
4806         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4807          size);
4808         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4809         LocalFree(buf);
4810     }
4811 }
4812
4813 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4814 {
4815     BOOL ret;
4816     LPBYTE buf = NULL;
4817     DWORD size = 0;
4818
4819     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4820      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4821      &buf, &size);
4822     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4823     if (buf)
4824     {
4825         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4826
4827         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4828          size);
4829         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4830         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4831         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4832         LocalFree(buf);
4833     }
4834     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4835      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4836      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4837     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4838     if (buf)
4839     {
4840         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4841
4842         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4843          size);
4844         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4845         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4846          "Unexpected key id\n");
4847         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4848         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4849         LocalFree(buf);
4850     }
4851     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4852      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4853      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4854     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4855     if (buf)
4856     {
4857         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4858
4859         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4860          size);
4861         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4862         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4863          "Unexpected issuer len\n");
4864         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4865          sizeof(encodedCommonName)), "Unexpected issuer\n");
4866         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4867         LocalFree(buf);
4868     }
4869     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4870      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4871      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4872     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4873     if (buf)
4874     {
4875         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4876
4877         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4878          size);
4879         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4880         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4881         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4882          "Unexpected serial number len\n");
4883         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4884          "Unexpected serial number\n");
4885         LocalFree(buf);
4886     }
4887 }
4888
4889 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4890  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4891  0x6f,0x72,0x67 };
4892
4893 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4894 {
4895     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4896     CERT_ALT_NAME_ENTRY entry = { 0 };
4897     BOOL ret;
4898     BYTE *buf = NULL;
4899     DWORD size = 0;
4900
4901     /* Test with empty id */
4902     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4903      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4904     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4905     if (buf)
4906     {
4907         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4908         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4909         LocalFree(buf);
4910     }
4911     /* With just a key id */
4912     info.KeyId.cbData = sizeof(keyId);
4913     info.KeyId.pbData = keyId;
4914     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4915      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4916     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4917     if (buf)
4918     {
4919         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4920          size);
4921         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4922         LocalFree(buf);
4923     }
4924     /* With a bogus issuer name */
4925     info.KeyId.cbData = 0;
4926     info.AuthorityCertIssuer.cAltEntry = 1;
4927     info.AuthorityCertIssuer.rgAltEntry = &entry;
4928     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4929      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4930     ok(!ret && GetLastError() == E_INVALIDARG,
4931      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4932     /* With an issuer name */
4933     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4934     U(entry).pwszURL = (LPWSTR)url;
4935     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4937     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4938     if (buf)
4939     {
4940         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4941          size);
4942         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4943          "Unexpected value\n");
4944         LocalFree(buf);
4945     }
4946     /* With just a serial number */
4947     info.AuthorityCertIssuer.cAltEntry = 0;
4948     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4949     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4950     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4951      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4952     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4953     if (buf)
4954     {
4955         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4956          size);
4957         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4958         LocalFree(buf);
4959     }
4960 }
4961
4962 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4963 {
4964     BOOL ret;
4965     LPBYTE buf = NULL;
4966     DWORD size = 0;
4967
4968     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4969      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4970      &buf, &size);
4971     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4972     if (buf)
4973     {
4974         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4975
4976         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4977          size);
4978         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4979         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4980          "Expected no issuer name entries\n");
4981         ok(info->AuthorityCertSerialNumber.cbData == 0,
4982          "Expected no serial number\n");
4983         LocalFree(buf);
4984     }
4985     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4986      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4987      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4988     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4989     if (buf)
4990     {
4991         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4992
4993         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4994          size);
4995         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4996         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4997          "Unexpected key id\n");
4998         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4999          "Expected no issuer name entries\n");
5000         ok(info->AuthorityCertSerialNumber.cbData == 0,
5001          "Expected no serial number\n");
5002         LocalFree(buf);
5003     }
5004     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5005      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5006      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5007     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5008     if (buf)
5009     {
5010         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5011
5012         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5013          size);
5014         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5015         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5016          "Expected 1 issuer entry, got %d\n",
5017          info->AuthorityCertIssuer.cAltEntry);
5018         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5019          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5020          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5021         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5022          url), "Unexpected URL\n");
5023         ok(info->AuthorityCertSerialNumber.cbData == 0,
5024          "Expected no serial number\n");
5025         LocalFree(buf);
5026     }
5027     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5028      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5029      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5030     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5031     if (buf)
5032     {
5033         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5034
5035         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5036          size);
5037         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5038         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5039          "Expected no issuer name entries\n");
5040         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5041          "Unexpected serial number len\n");
5042         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5043          sizeof(serialNum)), "Unexpected serial number\n");
5044         LocalFree(buf);
5045     }
5046 }
5047
5048 static const BYTE authorityInfoAccessWithUrl[] = {
5049 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5050 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5051 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5052 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5053 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5054 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5055
5056 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5057 {
5058     static char oid1[] = "1.2.3";
5059     static char oid2[] = "1.5.6";
5060     BOOL ret;
5061     BYTE *buf = NULL;
5062     DWORD size = 0;
5063     CERT_ACCESS_DESCRIPTION accessDescription[2];
5064     CERT_AUTHORITY_INFO_ACCESS aia;
5065
5066     memset(accessDescription, 0, sizeof(accessDescription));
5067     aia.cAccDescr = 0;
5068     aia.rgAccDescr = NULL;
5069     /* Having no access descriptions is allowed */
5070     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5071      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5072     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5073     if (buf)
5074     {
5075         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5076         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5077         LocalFree(buf);
5078         buf = NULL;
5079     }
5080     /* It can't have an empty access method */
5081     aia.cAccDescr = 1;
5082     aia.rgAccDescr = accessDescription;
5083     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5084      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5085     ok(!ret && (GetLastError() == E_INVALIDARG ||
5086      GetLastError() == OSS_LIMITED /* Win9x */),
5087      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5088     /* It can't have an empty location */
5089     accessDescription[0].pszAccessMethod = oid1;
5090     SetLastError(0xdeadbeef);
5091     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5092      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5093     ok(!ret && GetLastError() == E_INVALIDARG,
5094      "expected E_INVALIDARG, got %08x\n", GetLastError());
5095     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5096     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5097     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5098      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5099     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5100     if (buf)
5101     {
5102         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5103          size);
5104         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5105          "unexpected value\n");
5106         LocalFree(buf);
5107         buf = NULL;
5108     }
5109     accessDescription[1].pszAccessMethod = oid2;
5110     accessDescription[1].AccessLocation.dwAltNameChoice =
5111      CERT_ALT_NAME_IP_ADDRESS;
5112     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5113      sizeof(encodedIPAddr);
5114     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5115      (LPBYTE)encodedIPAddr;
5116     aia.cAccDescr = 2;
5117     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5118      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5119     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5120     if (buf)
5121     {
5122         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5123          "unexpected size %d\n", size);
5124         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5125          "unexpected value\n");
5126         LocalFree(buf);
5127         buf = NULL;
5128     }
5129 }
5130
5131 static void compareAuthorityInfoAccess(LPCSTR header,
5132  const CERT_AUTHORITY_INFO_ACCESS *expected,
5133  const CERT_AUTHORITY_INFO_ACCESS *got)
5134 {
5135     DWORD i;
5136
5137     ok(expected->cAccDescr == got->cAccDescr,
5138      "%s: expected %d access descriptions, got %d\n", header,
5139      expected->cAccDescr, got->cAccDescr);
5140     for (i = 0; i < expected->cAccDescr; i++)
5141     {
5142         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5143          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5144          header, i, expected->rgAccDescr[i].pszAccessMethod,
5145          got->rgAccDescr[i].pszAccessMethod);
5146         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5147          &got->rgAccDescr[i].AccessLocation);
5148     }
5149 }
5150
5151 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5152 {
5153     static char oid1[] = "1.2.3";
5154     static char oid2[] = "1.5.6";
5155     BOOL ret;
5156     LPBYTE buf = NULL;
5157     DWORD size = 0;
5158
5159     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5160      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5161      &buf, &size);
5162     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5163     if (buf)
5164     {
5165         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5166
5167         compareAuthorityInfoAccess("empty AIA", &aia,
5168          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5169         LocalFree(buf);
5170         buf = NULL;
5171     }
5172     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5173      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5174      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5175     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5176     if (buf)
5177     {
5178         CERT_ACCESS_DESCRIPTION accessDescription;
5179         CERT_AUTHORITY_INFO_ACCESS aia;
5180
5181         accessDescription.pszAccessMethod = oid1;
5182         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5183         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5184         aia.cAccDescr = 1;
5185         aia.rgAccDescr = &accessDescription;
5186         compareAuthorityInfoAccess("AIA with URL", &aia,
5187          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5188         LocalFree(buf);
5189         buf = NULL;
5190     }
5191     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5192      authorityInfoAccessWithUrlAndIPAddr,
5193      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5194      NULL, &buf, &size);
5195     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5196     if (buf)
5197     {
5198         CERT_ACCESS_DESCRIPTION accessDescription[2];
5199         CERT_AUTHORITY_INFO_ACCESS aia;
5200
5201         accessDescription[0].pszAccessMethod = oid1;
5202         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5203         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5204         accessDescription[1].pszAccessMethod = oid2;
5205         accessDescription[1].AccessLocation.dwAltNameChoice =
5206          CERT_ALT_NAME_IP_ADDRESS;
5207         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5208          sizeof(encodedIPAddr);
5209         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5210          (LPBYTE)encodedIPAddr;
5211         aia.cAccDescr = 2;
5212         aia.rgAccDescr = accessDescription;
5213         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5214          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5215         LocalFree(buf);
5216         buf = NULL;
5217     }
5218 }
5219
5220 static const BYTE emptyCTL[] = {
5221 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5222 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5223 static const BYTE emptyCTLWithVersion1[] = {
5224 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5225 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5226 static const BYTE ctlWithUsageIdentifier[] = {
5227 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5228 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5229 static const BYTE ctlWithListIdentifier[] = {
5230 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5231 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5232 static const BYTE ctlWithSequenceNumber[] = {
5233 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,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 ctlWithThisUpdate[] = {
5236 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5237 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5238 static const BYTE ctlWithThisAndNextUpdate[] = {
5239 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5240 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5241 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5242 static const BYTE ctlWithAlgId[] = {
5243 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5244 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5245 static const BYTE ctlWithBogusEntry[] = {
5246 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5247 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5248 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5249 static const BYTE ctlWithOneEntry[] = {
5250 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5251 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5252 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5253 static const BYTE ctlWithTwoEntries[] = {
5254 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5255 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5256 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5257 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5258 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5259
5260 static void test_encodeCTL(DWORD dwEncoding)
5261 {
5262     static char oid1[] = "1.2.3";
5263     static char oid2[] = "1.5.6";
5264     char *pOid1 = oid1;
5265     BOOL ret;
5266     BYTE *buf = NULL;
5267     DWORD size = 0;
5268     CTL_INFO info;
5269     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5270     CTL_ENTRY ctlEntry[2];
5271     CRYPT_ATTRIBUTE attr1, attr2;
5272     CRYPT_ATTR_BLOB value1, value2;
5273
5274     memset(&info, 0, sizeof(info));
5275     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5276      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5277     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5278     if (buf)
5279     {
5280         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5281         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5282         LocalFree(buf);
5283         buf = NULL;
5284     }
5285     info.dwVersion = 1;
5286     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5287      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5288     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5289     if (buf)
5290     {
5291         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5292         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5293         LocalFree(buf);
5294         buf = NULL;
5295     }
5296     info.dwVersion = 0;
5297     info.SubjectUsage.cUsageIdentifier = 1;
5298     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5299     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5300      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5301     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5302     if (buf)
5303     {
5304         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5305          size);
5306         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5307         LocalFree(buf);
5308         buf = NULL;
5309     }
5310     info.SubjectUsage.cUsageIdentifier = 0;
5311     info.ListIdentifier.cbData = sizeof(serialNum);
5312     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5313     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5314      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5316     if (buf)
5317     {
5318         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5319         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5320         LocalFree(buf);
5321         buf = NULL;
5322     }
5323     info.ListIdentifier.cbData = 0;
5324     info.SequenceNumber.cbData = sizeof(serialNum);
5325     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5326     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5327      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5328     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5329     if (buf)
5330     {
5331         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5332          size);
5333         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5334         LocalFree(buf);
5335         buf = NULL;
5336     }
5337     info.SequenceNumber.cbData = 0;
5338     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5339     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5340      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5341     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5342     if (buf)
5343     {
5344         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5345         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5346         LocalFree(buf);
5347         buf = NULL;
5348     }
5349     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5350     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5351      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5352     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5353     if (buf)
5354     {
5355         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5356          size);
5357         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5358         LocalFree(buf);
5359         buf = NULL;
5360     }
5361     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5362     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5363     info.SubjectAlgorithm.pszObjId = oid2;
5364     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5365      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5366     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5367     if (buf)
5368     {
5369         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5370         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5371         LocalFree(buf);
5372         buf = NULL;
5373     }
5374     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5375      * (see tests below) but it'll encode fine.
5376      */
5377     info.SubjectAlgorithm.pszObjId = NULL;
5378     value1.cbData = sizeof(serialNum);
5379     value1.pbData = (LPBYTE)serialNum;
5380     attr1.pszObjId = oid1;
5381     attr1.cValue = 1;
5382     attr1.rgValue = &value1;
5383     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5384     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5385     ctlEntry[0].cAttribute = 1;
5386     ctlEntry[0].rgAttribute = &attr1;
5387     info.cCTLEntry = 1;
5388     info.rgCTLEntry = ctlEntry;
5389     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5390      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5391     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5392     if (buf)
5393     {
5394         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5395         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5396         LocalFree(buf);
5397         buf = NULL;
5398     }
5399     value1.cbData = sizeof(emptySequence);
5400     value1.pbData = (LPBYTE)emptySequence;
5401     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5402      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5403     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5404     if (buf)
5405     {
5406         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5407         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5408         LocalFree(buf);
5409         buf = NULL;
5410     }
5411     value2.cbData = sizeof(encodedIPAddr);
5412     value2.pbData = (LPBYTE)encodedIPAddr;
5413     attr2.pszObjId = oid2;
5414     attr2.cValue = 1;
5415     attr2.rgValue = &value2;
5416     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5417     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5418     ctlEntry[1].cAttribute = 1;
5419     ctlEntry[1].rgAttribute = &attr2;
5420     info.cCTLEntry = 2;
5421     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5422      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5423     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5424     if (buf)
5425     {
5426         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5427         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5428         LocalFree(buf);
5429         buf = NULL;
5430     }
5431 }
5432
5433 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5434  const CTL_INFO *got)
5435 {
5436     DWORD i, j, k;
5437
5438     ok(expected->dwVersion == got->dwVersion,
5439      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5440      got->dwVersion);
5441     ok(expected->SubjectUsage.cUsageIdentifier ==
5442      got->SubjectUsage.cUsageIdentifier,
5443      "%s: expected %d usage identifiers, got %d\n", header,
5444      expected->SubjectUsage.cUsageIdentifier,
5445      got->SubjectUsage.cUsageIdentifier);
5446     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5447         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5448          got->SubjectUsage.rgpszUsageIdentifier[i]),
5449          "%s[%d]: expected %s, got %s\n", header, i,
5450          expected->SubjectUsage.rgpszUsageIdentifier[i],
5451          got->SubjectUsage.rgpszUsageIdentifier[i]);
5452     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5453      "%s: expected list identifier of %d bytes, got %d\n", header,
5454      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5455     if (expected->ListIdentifier.cbData)
5456         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5457          expected->ListIdentifier.cbData),
5458          "%s: unexpected list identifier value\n", header);
5459     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5460      "%s: expected sequence number of %d bytes, got %d\n", header,
5461      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5462     if (expected->SequenceNumber.cbData)
5463         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5464          expected->SequenceNumber.cbData),
5465          "%s: unexpected sequence number value\n", header);
5466     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5467      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5468      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5469      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5470     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5471      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5472      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5473      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5474     if (expected->SubjectAlgorithm.pszObjId &&
5475      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5476         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5477          expected->SubjectAlgorithm.pszObjId);
5478     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5479         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5480          got->SubjectAlgorithm.pszObjId),
5481          "%s: expected subject algorithm %s, got %s\n", header,
5482          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5483     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5484      got->SubjectAlgorithm.Parameters.cbData,
5485      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5486      expected->SubjectAlgorithm.Parameters.cbData,
5487      got->SubjectAlgorithm.Parameters.cbData);
5488     if (expected->SubjectAlgorithm.Parameters.cbData)
5489         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5490          got->SubjectAlgorithm.Parameters.pbData,
5491          expected->SubjectAlgorithm.Parameters.cbData),
5492          "%s: unexpected subject algorithm parameter value\n", header);
5493     ok(expected->cCTLEntry == got->cCTLEntry,
5494      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5495      got->cCTLEntry);
5496     for (i = 0; i < expected->cCTLEntry; i++)
5497     {
5498         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5499          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5500          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5501          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5502          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5503         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5504             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5505              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5506              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5507              "%s[%d]: unexpected subject identifier value\n",
5508              header, i);
5509         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5510         {
5511             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5512              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5513              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5514              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5515              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5516             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5517             {
5518                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5519                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5520                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5521                  header, i, j, k,
5522                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5523                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5524                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5525                     ok(!memcmp(
5526                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5527                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5528                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5529                      "%s[%d][%d][%d]: unexpected value\n",
5530                      header, i, j, k);
5531             }
5532         }
5533     }
5534     ok(expected->cExtension == got->cExtension,
5535      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5536      got->cExtension);
5537     for (i = 0; i < expected->cExtension; i++)
5538     {
5539         ok(!strcmp(expected->rgExtension[i].pszObjId,
5540          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5541          header, i, expected->rgExtension[i].pszObjId,
5542          got->rgExtension[i].pszObjId);
5543         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5544          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5545          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5546         ok(expected->rgExtension[i].Value.cbData ==
5547          got->rgExtension[i].Value.cbData,
5548          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5549          header, i, expected->rgExtension[i].Value.cbData,
5550          got->rgExtension[i].Value.cbData);
5551         if (expected->rgExtension[i].Value.cbData)
5552             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5553              got->rgExtension[i].Value.pbData,
5554              expected->rgExtension[i].Value.cbData),
5555              "%s[%d]: unexpected extension value\n", header, i);
5556     }
5557 }
5558
5559 static const BYTE signedCTL[] = {
5560 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5561 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5562 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5563 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5564 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5565 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5566 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5567 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5568 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5569 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5570 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5571 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5572 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5573 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5574 static const BYTE signedCTLWithCTLInnerContent[] = {
5575 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5576 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5577 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5578 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5579 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5580 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5581 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5582 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5583 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5584 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5585 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5586 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5587 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5588 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5589 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5590 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5591 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5592 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5593 0x57,0x6c,0x0b,0x47,0xb8 };
5594
5595 static void test_decodeCTL(DWORD dwEncoding)
5596 {
5597     static char oid1[] = "1.2.3";
5598     static char oid2[] = "1.5.6";
5599     static BYTE nullData[] = { 5,0 };
5600     char *pOid1 = oid1;
5601     BOOL ret;
5602     BYTE *buf = NULL;
5603     DWORD size = 0;
5604     CTL_INFO info;
5605     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5606     CTL_ENTRY ctlEntry[2];
5607     CRYPT_ATTRIBUTE attr1, attr2;
5608     CRYPT_ATTR_BLOB value1, value2;
5609
5610     memset(&info, 0, sizeof(info));
5611     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5612      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5613     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5614     if (buf)
5615     {
5616         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5617         LocalFree(buf);
5618         buf = NULL;
5619     }
5620     info.dwVersion = 1;
5621     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5622      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5623      &size);
5624     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5625     if (buf)
5626     {
5627         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5628         LocalFree(buf);
5629         buf = NULL;
5630     }
5631     info.dwVersion = 0;
5632     info.SubjectUsage.cUsageIdentifier = 1;
5633     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5634     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5635      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5636      &buf, &size);
5637     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5638     if (buf)
5639     {
5640         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5641         LocalFree(buf);
5642         buf = NULL;
5643     }
5644     info.SubjectUsage.cUsageIdentifier = 0;
5645     info.ListIdentifier.cbData = sizeof(serialNum);
5646     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5647     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5648      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5649     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5650     if (buf)
5651     {
5652         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5653         LocalFree(buf);
5654         buf = NULL;
5655     }
5656     info.ListIdentifier.cbData = 0;
5657     info.SequenceNumber.cbData = sizeof(serialNum);
5658     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5659     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5660      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5661     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5662     if (buf)
5663     {
5664         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5665         LocalFree(buf);
5666         buf = NULL;
5667     }
5668     info.SequenceNumber.cbData = 0;
5669     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5670     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5671      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5672     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5673     if (buf)
5674     {
5675         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5676         LocalFree(buf);
5677         buf = NULL;
5678     }
5679     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5680     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5681      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5682      &buf, &size);
5683     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5684     if (buf)
5685     {
5686         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5687         LocalFree(buf);
5688         buf = NULL;
5689     }
5690     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5691     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5692     info.SubjectAlgorithm.pszObjId = oid2;
5693     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5694     info.SubjectAlgorithm.Parameters.pbData = nullData;
5695     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5696      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5697     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5698     if (buf)
5699     {
5700         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5701         LocalFree(buf);
5702         buf = NULL;
5703     }
5704     SetLastError(0xdeadbeef);
5705     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5706      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5707     ok(!ret &&
5708      (GetLastError() == CRYPT_E_ASN1_EOD ||
5709       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5710       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5711      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5712      GetLastError());
5713     info.SubjectAlgorithm.Parameters.cbData = 0;
5714     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5715     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5716     info.SubjectAlgorithm.pszObjId = oid2;
5717     info.SubjectAlgorithm.pszObjId = NULL;
5718     value1.cbData = sizeof(emptySequence);
5719     value1.pbData = (LPBYTE)emptySequence;
5720     attr1.pszObjId = oid1;
5721     attr1.cValue = 1;
5722     attr1.rgValue = &value1;
5723     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5724     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5725     ctlEntry[0].cAttribute = 1;
5726     ctlEntry[0].rgAttribute = &attr1;
5727     info.cCTLEntry = 1;
5728     info.rgCTLEntry = ctlEntry;
5729     SetLastError(0xdeadbeef);
5730     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5731      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5732     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5733     if (buf)
5734     {
5735         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5736         LocalFree(buf);
5737         buf = NULL;
5738     }
5739     value2.cbData = sizeof(encodedIPAddr);
5740     value2.pbData = (LPBYTE)encodedIPAddr;
5741     attr2.pszObjId = oid2;
5742     attr2.cValue = 1;
5743     attr2.rgValue = &value2;
5744     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5745     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5746     ctlEntry[1].cAttribute = 1;
5747     ctlEntry[1].rgAttribute = &attr2;
5748     info.cCTLEntry = 2;
5749     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5750      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5751     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5752     if (buf)
5753     {
5754         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5755         LocalFree(buf);
5756         buf = NULL;
5757     }
5758     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5759     SetLastError(0xdeadbeef);
5760     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5761      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5762     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5763      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5764      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5765      GetLastError());
5766     SetLastError(0xdeadbeef);
5767     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5768      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5769      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5770     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5771      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5772      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5773      GetLastError());
5774 }
5775
5776 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5777 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5778  0x03,0,0,0,0,0,0 };
5779 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5780  0xa0,0x01,0x01 };
5781 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5782  0x03,0x02,0x01,0x01 };
5783 static BYTE bogusDER[] = { 1 };
5784
5785 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5786 {
5787     BOOL ret;
5788     BYTE *buf = NULL;
5789     DWORD size = 0;
5790     CRYPT_CONTENT_INFO info = { 0 };
5791     char oid1[] = "1.2.3";
5792
5793     if (0)
5794     {
5795         /* Crashes on win9x */
5796         SetLastError(0xdeadbeef);
5797         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5798          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5799         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5800          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5801     }
5802     SetLastError(0xdeadbeef);
5803     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5804      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5805     ok(!ret && (GetLastError() == E_INVALIDARG ||
5806      GetLastError() == OSS_LIMITED /* Win9x */),
5807      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5808     info.pszObjId = oid1;
5809     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5810      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5811     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5812     if (buf)
5813     {
5814         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5815         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5816         LocalFree(buf);
5817     }
5818     info.Content.pbData = bogusDER;
5819     info.Content.cbData = sizeof(bogusDER);
5820     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5821      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5822     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5823     if (buf)
5824     {
5825         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5826         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5827         LocalFree(buf);
5828     }
5829     info.Content.pbData = (BYTE *)ints[0].encoded;
5830     info.Content.cbData = ints[0].encoded[1] + 2;
5831     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5833     if (buf)
5834     {
5835         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5836         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5837         LocalFree(buf);
5838     }
5839 }
5840
5841 static const BYTE indefiniteSignedPKCSContent[] = {
5842 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5843 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5844 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5845 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5846 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5847 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5848 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5849 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5850 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5851 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5852 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5853 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5854 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5855 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5856 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5857 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5858 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5859 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5860 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5861 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5862 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5863 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5864 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5865 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5866 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5867 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5868 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5869 0x00,0x00,0x00,0x00,0x00,0x00 };
5870
5871 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5872 {
5873     BOOL ret;
5874     LPBYTE buf = NULL;
5875     DWORD size = 0;
5876     CRYPT_CONTENT_INFO *info;
5877
5878     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5879      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5880      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5881     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5882     if (buf)
5883     {
5884         info = (CRYPT_CONTENT_INFO *)buf;
5885
5886         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5887          info->pszObjId);
5888         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5889          info->Content.cbData);
5890         LocalFree(buf);
5891     }
5892     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5893      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5894      0, NULL, NULL, &size);
5895     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5896     SetLastError(0xdeadbeef);
5897     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5898      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5899      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5900     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5901      * I doubt an app depends on that.
5902      */
5903     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5904      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5905      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5906      GetLastError());
5907     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5908      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5909      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5910     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5911     if (buf)
5912     {
5913         info = (CRYPT_CONTENT_INFO *)buf;
5914
5915         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5916          info->pszObjId);
5917         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5918          "Unexpected size %d\n", info->Content.cbData);
5919         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5920          info->Content.cbData), "Unexpected value\n");
5921         LocalFree(buf);
5922     }
5923     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5924      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5925      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5926     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5927     if (buf)
5928     {
5929         info = (CRYPT_CONTENT_INFO *)buf;
5930
5931         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5932          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5933         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5934          info->Content.cbData);
5935         LocalFree(buf);
5936     }
5937 }
5938
5939 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5940  0x00 };
5941 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5942  0x01 };
5943 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5944  0x02,0x01,0x01 };
5945
5946 static void test_encodePKCSAttribute(DWORD dwEncoding)
5947 {
5948     CRYPT_ATTRIBUTE attr = { 0 };
5949     BOOL ret;
5950     LPBYTE buf = NULL;
5951     DWORD size = 0;
5952     CRYPT_ATTR_BLOB blob;
5953     char oid[] = "1.2.3";
5954
5955     if (0)
5956     {
5957         /* Crashes on win9x */
5958         SetLastError(0xdeadbeef);
5959         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5960          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5961         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5962          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5963     }
5964     SetLastError(0xdeadbeef);
5965     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5966      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5967     ok(!ret && (GetLastError() == E_INVALIDARG ||
5968      GetLastError() == OSS_LIMITED /* Win9x */),
5969      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5970     attr.pszObjId = oid;
5971     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5972      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5973     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5974     if (buf)
5975     {
5976         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5977         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5978         LocalFree(buf);
5979     }
5980     blob.cbData = sizeof(bogusDER);
5981     blob.pbData = bogusDER;
5982     attr.cValue = 1;
5983     attr.rgValue = &blob;
5984     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5985      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5986     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5987     if (buf)
5988     {
5989         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5990         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5991         LocalFree(buf);
5992     }
5993     blob.pbData = (BYTE *)ints[0].encoded;
5994     blob.cbData = ints[0].encoded[1] + 2;
5995     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5996      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5997     if (buf)
5998     {
5999         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6000         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6001         LocalFree(buf);
6002     }
6003 }
6004
6005 static void test_decodePKCSAttribute(DWORD dwEncoding)
6006 {
6007     BOOL ret;
6008     LPBYTE buf = NULL;
6009     DWORD size = 0;
6010     CRYPT_ATTRIBUTE *attr;
6011
6012     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6013      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6014      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6015     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6016     if (buf)
6017     {
6018         attr = (CRYPT_ATTRIBUTE *)buf;
6019
6020         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6021          attr->pszObjId);
6022         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6023         LocalFree(buf);
6024     }
6025     SetLastError(0xdeadbeef);
6026     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6027      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6028      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6029     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6030      * I doubt an app depends on that.
6031      */
6032     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6033      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6034      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6035      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6036      GetLastError());
6037     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6038      intPKCSAttr, sizeof(intPKCSAttr),
6039      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6040     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6041     if (buf)
6042     {
6043         attr = (CRYPT_ATTRIBUTE *)buf;
6044
6045         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6046          attr->pszObjId);
6047         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6048         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6049          "Unexpected size %d\n", attr->rgValue[0].cbData);
6050         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6051          attr->rgValue[0].cbData), "Unexpected value\n");
6052         LocalFree(buf);
6053     }
6054 }
6055
6056 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6057 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6058  0x2a,0x03,0x31,0x00 };
6059 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6060  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6061
6062 static void test_encodePKCSAttributes(DWORD dwEncoding)
6063 {
6064     CRYPT_ATTRIBUTES attributes = { 0 };
6065     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6066     CRYPT_ATTR_BLOB blob;
6067     BOOL ret;
6068     LPBYTE buf = NULL;
6069     DWORD size = 0;
6070     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6071
6072     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6073      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6074     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6075     if (buf)
6076     {
6077         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6078         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6079         LocalFree(buf);
6080     }
6081     attributes.cAttr = 1;
6082     attributes.rgAttr = attr;
6083     SetLastError(0xdeadbeef);
6084     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6085      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6086     ok(!ret && (GetLastError() == E_INVALIDARG ||
6087      GetLastError() == OSS_LIMITED /* Win9x */),
6088      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6089     attr[0].pszObjId = oid1;
6090     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6091      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6092     if (buf)
6093     {
6094         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6095         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6096         LocalFree(buf);
6097     }
6098     attr[1].pszObjId = oid2;
6099     attr[1].cValue = 1;
6100     attr[1].rgValue = &blob;
6101     blob.pbData = (BYTE *)ints[0].encoded;
6102     blob.cbData = ints[0].encoded[1] + 2;
6103     attributes.cAttr = 2;
6104     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6105      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6106     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6107     if (buf)
6108     {
6109         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6110         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6111         LocalFree(buf);
6112     }
6113 }
6114
6115 static void test_decodePKCSAttributes(DWORD dwEncoding)
6116 {
6117     BOOL ret;
6118     LPBYTE buf = NULL;
6119     DWORD size = 0;
6120     CRYPT_ATTRIBUTES *attributes;
6121
6122     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6123      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6124      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6125     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6126     if (buf)
6127     {
6128         attributes = (CRYPT_ATTRIBUTES *)buf;
6129         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6130          attributes->cAttr);
6131         LocalFree(buf);
6132     }
6133     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6134      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6135      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6136     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6137     if (buf)
6138     {
6139         attributes = (CRYPT_ATTRIBUTES *)buf;
6140         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6141          attributes->cAttr);
6142         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6143          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6144         ok(attributes->rgAttr[0].cValue == 0,
6145          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6146         LocalFree(buf);
6147     }
6148     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6149      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6150      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6151     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6152     if (buf)
6153     {
6154         attributes = (CRYPT_ATTRIBUTES *)buf;
6155         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6156          attributes->cAttr);
6157         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6158          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6159         ok(attributes->rgAttr[0].cValue == 0,
6160          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6161         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6162          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6163         ok(attributes->rgAttr[1].cValue == 1,
6164          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6165         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6166          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6167         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6168          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6169         LocalFree(buf);
6170     }
6171 }
6172
6173 static const BYTE singleCapability[] = {
6174 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6175 static const BYTE twoCapabilities[] = {
6176 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6177 static const BYTE singleCapabilitywithNULL[] = {
6178 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6179
6180 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6181 {
6182     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6183     BOOL ret;
6184     LPBYTE buf = NULL;
6185     DWORD size = 0;
6186     CRYPT_SMIME_CAPABILITY capability[2];
6187     CRYPT_SMIME_CAPABILITIES capabilities;
6188
6189     /* An empty capabilities is allowed */
6190     capabilities.cCapability = 0;
6191     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6192      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6193     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6194     if (buf)
6195     {
6196         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6197         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6198         LocalFree(buf);
6199     }
6200     /* A non-empty capabilities with an empty capability (lacking an OID) is
6201      * not allowed
6202      */
6203     capability[0].pszObjId = NULL;
6204     capability[0].Parameters.cbData = 0;
6205     capabilities.cCapability = 1;
6206     capabilities.rgCapability = capability;
6207     SetLastError(0xdeadbeef);
6208     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6209      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6210     ok(!ret && (GetLastError() == E_INVALIDARG ||
6211      GetLastError() == OSS_LIMITED /* Win9x */),
6212      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6213     capability[0].pszObjId = oid1;
6214     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6215      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6216     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6217     if (buf)
6218     {
6219         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6220         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6221         LocalFree(buf);
6222     }
6223     capability[1].pszObjId = oid2;
6224     capability[1].Parameters.cbData = 0;
6225     capabilities.cCapability = 2;
6226     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6227      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6228     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6229     if (buf)
6230     {
6231         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6232         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6233         LocalFree(buf);
6234     }
6235 }
6236
6237 static void compareSMimeCapabilities(LPCSTR header,
6238  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6239 {
6240     DWORD i;
6241
6242     ok(got->cCapability == expected->cCapability,
6243      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6244      got->cCapability);
6245     for (i = 0; i < expected->cCapability; i++)
6246     {
6247         ok(!strcmp(expected->rgCapability[i].pszObjId,
6248          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6249          header, i, expected->rgCapability[i].pszObjId,
6250          got->rgCapability[i].pszObjId);
6251         ok(expected->rgCapability[i].Parameters.cbData ==
6252          got->rgCapability[i].Parameters.cbData,
6253          "%s[%d]: expected %d bytes, got %d\n", header, i,
6254          expected->rgCapability[i].Parameters.cbData,
6255          got->rgCapability[i].Parameters.cbData);
6256         if (expected->rgCapability[i].Parameters.cbData)
6257             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6258              got->rgCapability[i].Parameters.pbData,
6259              expected->rgCapability[i].Parameters.cbData),
6260              "%s[%d]: unexpected value\n", header, i);
6261     }
6262 }
6263
6264 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6265 {
6266     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6267     BOOL ret;
6268     DWORD size = 0;
6269     CRYPT_SMIME_CAPABILITY capability[2];
6270     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6271
6272     SetLastError(0xdeadbeef);
6273     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6274      emptySequence, sizeof(emptySequence),
6275      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6276     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6277     if (ret)
6278     {
6279         capabilities.cCapability = 0;
6280         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6281         LocalFree(ptr);
6282     }
6283     SetLastError(0xdeadbeef);
6284     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6285      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6286      &ptr, &size);
6287     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6288     if (ret)
6289     {
6290         capability[0].pszObjId = oid1;
6291         capability[0].Parameters.cbData = 0;
6292         capabilities.cCapability = 1;
6293         capabilities.rgCapability = capability;
6294         compareSMimeCapabilities("single capability", &capabilities, ptr);
6295         LocalFree(ptr);
6296     }
6297     SetLastError(0xdeadbeef);
6298     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6299      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6300      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6301     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6302     if (ret)
6303     {
6304         BYTE NULLparam[] = {0x05, 0x00};
6305         capability[0].pszObjId = oid1;
6306         capability[0].Parameters.cbData = 2;
6307         capability[0].Parameters.pbData = NULLparam;
6308         capabilities.cCapability = 1;
6309         capabilities.rgCapability = capability;
6310         compareSMimeCapabilities("single capability with NULL", &capabilities,
6311          ptr);
6312         LocalFree(ptr);
6313     }
6314     SetLastError(0xdeadbeef);
6315     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6316     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6317     &ptr, &size);
6318     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6319     if (ret)
6320     {
6321         capability[0].Parameters.cbData = 0;
6322         capability[1].pszObjId = oid2;
6323         capability[1].Parameters.cbData = 0;
6324         capabilities.cCapability = 2;
6325         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6326         LocalFree(ptr);
6327     }
6328 }
6329
6330 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6331  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6332  0x67 };
6333 static const BYTE minimalPKCSSigner[] = {
6334  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6335  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6336  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6337 static const BYTE PKCSSignerWithSerial[] = {
6338  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6339  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6340  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6341  0x00 };
6342 static const BYTE PKCSSignerWithHashAlgo[] = {
6343  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,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  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6346  0x00,0x04,0x00 };
6347 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6348  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6349  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6350  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6351  0x06,0x05,0x00,0x04,0x00 };
6352 static const BYTE PKCSSignerWithHash[] = {
6353  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6354  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6355  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6356  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6357  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6358 static const BYTE PKCSSignerWithAuthAttr[] = {
6359 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6360 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6361 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6362 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6363 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6364 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6365 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6366
6367 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6368 {
6369     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6370     BOOL ret;
6371     LPBYTE buf = NULL;
6372     DWORD size = 0;
6373     CMSG_SIGNER_INFO info = { 0 };
6374     char oid_common_name[] = szOID_COMMON_NAME;
6375     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6376      (LPBYTE)encodedCommonName };
6377     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6378
6379     SetLastError(0xdeadbeef);
6380     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6381      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6382     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6383     {
6384         skip("no PKCS7_SIGNER_INFO encode support\n");
6385         return;
6386     }
6387     ok(!ret && (GetLastError() == E_INVALIDARG ||
6388      GetLastError() == OSS_LIMITED /* Win9x */),
6389      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6390     /* To be encoded, a signer must have an issuer at least, and the encoding
6391      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6392      * see decoding tests.)
6393      */
6394     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6395     info.Issuer.pbData = encodedCommonNameNoNull;
6396     SetLastError(0xdeadbeef);
6397     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6398      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6399     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6400         ok(!ret && GetLastError() == E_INVALIDARG,
6401          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6402     else
6403     {
6404         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6405          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6406         if (buf)
6407         {
6408             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6409             if (size == sizeof(minimalPKCSSigner))
6410                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6411             else
6412                 ok(0, "Unexpected value\n");
6413             LocalFree(buf);
6414         }
6415     }
6416     info.SerialNumber.cbData = sizeof(serialNum);
6417     info.SerialNumber.pbData = (BYTE *)serialNum;
6418     SetLastError(0xdeadbeef);
6419     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6420      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6421     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6422         ok(!ret && GetLastError() == E_INVALIDARG,
6423          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6424     else
6425     {
6426         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6427          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6428         if (buf)
6429         {
6430             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6431              size);
6432             if (size == sizeof(PKCSSignerWithSerial))
6433                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6434                  "Unexpected value\n");
6435             else
6436                 ok(0, "Unexpected value\n");
6437             LocalFree(buf);
6438         }
6439     }
6440     info.HashAlgorithm.pszObjId = oid1;
6441     SetLastError(0xdeadbeef);
6442     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6443      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6444     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6445         ok(!ret && GetLastError() == E_INVALIDARG,
6446          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6447     else
6448     {
6449         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6450          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6451         if (buf)
6452         {
6453             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6454              size);
6455             if (size == sizeof(PKCSSignerWithHashAlgo))
6456                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6457                  "Unexpected value\n");
6458             else
6459                 ok(0, "Unexpected value\n");
6460             LocalFree(buf);
6461         }
6462     }
6463     info.HashEncryptionAlgorithm.pszObjId = oid2;
6464     SetLastError(0xdeadbeef);
6465     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6466      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6467     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6468         ok(!ret && GetLastError() == E_INVALIDARG,
6469          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6470     else
6471     {
6472         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6473         if (buf)
6474         {
6475             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6476              "Unexpected size %d\n", size);
6477             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6478                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6479                  "Unexpected value\n");
6480             else
6481                 ok(0, "Unexpected value\n");
6482             LocalFree(buf);
6483         }
6484     }
6485     info.EncryptedHash.cbData = sizeof(hash);
6486     info.EncryptedHash.pbData = (BYTE *)hash;
6487     SetLastError(0xdeadbeef);
6488     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6489      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6490     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6491         ok(!ret && GetLastError() == E_INVALIDARG,
6492          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6493     else
6494     {
6495         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6496         if (buf)
6497         {
6498             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6499              size);
6500             if (size == sizeof(PKCSSignerWithHash))
6501                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6502                  "Unexpected value\n");
6503             else
6504                 ok(0, "Unexpected value\n");
6505             LocalFree(buf);
6506         }
6507     }
6508     info.AuthAttrs.cAttr = 1;
6509     info.AuthAttrs.rgAttr = &attr;
6510     SetLastError(0xdeadbeef);
6511     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6512      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6513     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6514         ok(!ret && GetLastError() == E_INVALIDARG,
6515          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6516     else
6517     {
6518         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6519         if (buf)
6520         {
6521             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6522              size);
6523             if (size == sizeof(PKCSSignerWithAuthAttr))
6524                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6525                  "Unexpected value\n");
6526             else
6527                 ok(0, "Unexpected value\n");
6528             LocalFree(buf);
6529         }
6530     }
6531 }
6532
6533 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6534 {
6535     BOOL ret;
6536     LPBYTE buf = NULL;
6537     DWORD size = 0;
6538     CMSG_SIGNER_INFO *info;
6539
6540     /* A PKCS signer can't be decoded without a serial number. */
6541     SetLastError(0xdeadbeef);
6542     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6543      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6544      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6545     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6546      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6547      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6548      GetLastError());
6549     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6550      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6551      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6552     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6553      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6554     if (buf)
6555     {
6556         info = (CMSG_SIGNER_INFO *)buf;
6557         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6558          info->dwVersion);
6559         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6560          "Unexpected size %d\n", info->Issuer.cbData);
6561         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6562          info->Issuer.cbData), "Unexpected value\n");
6563         ok(info->SerialNumber.cbData == sizeof(serialNum),
6564          "Unexpected size %d\n", info->SerialNumber.cbData);
6565         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6566          "Unexpected value\n");
6567         LocalFree(buf);
6568     }
6569     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6570      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6571      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6572     if (buf)
6573     {
6574         info = (CMSG_SIGNER_INFO *)buf;
6575         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6576          info->dwVersion);
6577         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6578          "Unexpected size %d\n", info->Issuer.cbData);
6579         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6580          info->Issuer.cbData), "Unexpected value\n");
6581         ok(info->SerialNumber.cbData == sizeof(serialNum),
6582          "Unexpected size %d\n", info->SerialNumber.cbData);
6583         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6584          "Unexpected value\n");
6585         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6586          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6587         LocalFree(buf);
6588     }
6589     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6590      PKCSSignerWithHashAndEncryptionAlgo,
6591      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6592      NULL, &buf, &size);
6593     if (buf)
6594     {
6595         info = (CMSG_SIGNER_INFO *)buf;
6596         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6597          info->dwVersion);
6598         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6599          "Unexpected size %d\n", info->Issuer.cbData);
6600         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6601          info->Issuer.cbData), "Unexpected value\n");
6602         ok(info->SerialNumber.cbData == sizeof(serialNum),
6603          "Unexpected size %d\n", info->SerialNumber.cbData);
6604         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6605          "Unexpected value\n");
6606         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6607          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6608         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6609          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6610         LocalFree(buf);
6611     }
6612     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6613      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6614      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6615     if (buf)
6616     {
6617         info = (CMSG_SIGNER_INFO *)buf;
6618         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6619          info->dwVersion);
6620         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6621          "Unexpected size %d\n", info->Issuer.cbData);
6622         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6623          info->Issuer.cbData), "Unexpected value\n");
6624         ok(info->SerialNumber.cbData == sizeof(serialNum),
6625          "Unexpected size %d\n", info->SerialNumber.cbData);
6626         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6627          "Unexpected value\n");
6628         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6629          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6630         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6631          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6632         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6633          info->EncryptedHash.cbData);
6634         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6635          "Unexpected value\n");
6636         LocalFree(buf);
6637     }
6638     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6639      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6640      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6641     if (buf)
6642     {
6643         info = (CMSG_SIGNER_INFO *)buf;
6644         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6645          info->AuthAttrs.cAttr);
6646         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6647          "Expected %s, got %s\n", szOID_COMMON_NAME,
6648          info->AuthAttrs.rgAttr[0].pszObjId);
6649         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6650          info->AuthAttrs.rgAttr[0].cValue);
6651         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6652          sizeof(encodedCommonName), "Unexpected size %d\n",
6653          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6654         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6655          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6656         LocalFree(buf);
6657     }
6658 }
6659
6660 static const BYTE CMSSignerWithKeyId[] = {
6661 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6662 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6663
6664 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6665 {
6666     BOOL ret;
6667     LPBYTE buf = NULL;
6668     DWORD size = 0;
6669     CMSG_CMS_SIGNER_INFO info = { 0 };
6670     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6671
6672     SetLastError(0xdeadbeef);
6673     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6674      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6675     ok(!ret, "Expected failure, got %d\n", ret);
6676     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6677     {
6678         skip("no CMS_SIGNER_INFO encode support\n");
6679         return;
6680     }
6681     ok(GetLastError() == E_INVALIDARG,
6682        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6683     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6684     SetLastError(0xdeadbeef);
6685     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6686      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6687     ok(!ret, "Expected failure, got %d\n", ret);
6688     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6689     {
6690         skip("no CMS_SIGNER_INFO encode support\n");
6691         return;
6692     }
6693     ok(GetLastError() == E_INVALIDARG,
6694        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6695     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6696      * be a key id or a issuer serial number with at least the issuer set, and
6697      * the encoding must include PKCS_7_ASN_ENCODING.
6698      * (That isn't enough to be decoded, see decoding tests.)
6699      */
6700     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6701      sizeof(encodedCommonNameNoNull);
6702     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6703     SetLastError(0xdeadbeef);
6704     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6705      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6706     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6707         ok(!ret && GetLastError() == E_INVALIDARG,
6708          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6709     else
6710     {
6711         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6712         if (buf)
6713         {
6714             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6715             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6716             LocalFree(buf);
6717         }
6718     }
6719     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6720     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6721     SetLastError(0xdeadbeef);
6722     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6723      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6724     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6725         ok(!ret && GetLastError() == E_INVALIDARG,
6726          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6727     else
6728     {
6729         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6730         if (buf)
6731         {
6732             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6733              size);
6734             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6735             LocalFree(buf);
6736         }
6737     }
6738     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6739     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6740     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6741     SetLastError(0xdeadbeef);
6742     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6743      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6744     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6745         ok(!ret && GetLastError() == E_INVALIDARG,
6746          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6747     else
6748     {
6749         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6750         if (buf)
6751         {
6752             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6753              size);
6754             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6755             LocalFree(buf);
6756         }
6757     }
6758     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6759      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6760      * (see RFC 3852, section 5.3.)
6761      */
6762     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6763     U(info.SignerId).HashId.cbData = sizeof(hash);
6764     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6765     SetLastError(0xdeadbeef);
6766     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6767      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6768     ok(!ret && GetLastError() == E_INVALIDARG,
6769      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6770     /* Now with a hash algo */
6771     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6772     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6773      sizeof(encodedCommonNameNoNull);
6774     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6775     info.HashAlgorithm.pszObjId = oid1;
6776     SetLastError(0xdeadbeef);
6777     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6778      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6779     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6780         ok(!ret && GetLastError() == E_INVALIDARG,
6781          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6782     else
6783     {
6784         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6785         if (buf)
6786         {
6787             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6788              size);
6789             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6790              "Unexpected value\n");
6791             LocalFree(buf);
6792         }
6793     }
6794     info.HashEncryptionAlgorithm.pszObjId = oid2;
6795     SetLastError(0xdeadbeef);
6796     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6797      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6798     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6799         ok(!ret && GetLastError() == E_INVALIDARG,
6800          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6801     else
6802     {
6803         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6804         if (buf)
6805         {
6806             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6807              "Unexpected size %d\n", size);
6808             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6809              "Unexpected value\n");
6810             LocalFree(buf);
6811         }
6812     }
6813     info.EncryptedHash.cbData = sizeof(hash);
6814     info.EncryptedHash.pbData = (BYTE *)hash;
6815     SetLastError(0xdeadbeef);
6816     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6817      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6818     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6819         ok(!ret && GetLastError() == E_INVALIDARG,
6820          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6821     else
6822     {
6823         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6824         if (buf)
6825         {
6826             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6827              size);
6828             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6829             LocalFree(buf);
6830         }
6831     }
6832 }
6833
6834 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6835 {
6836     BOOL ret;
6837     LPBYTE buf = NULL;
6838     DWORD size = 0;
6839     CMSG_CMS_SIGNER_INFO *info;
6840     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6841
6842     /* A CMS signer can't be decoded without a serial number. */
6843     SetLastError(0xdeadbeef);
6844     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6845      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6846      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6847     ok(!ret, "expected failure\n");
6848     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6849     {
6850         skip("no CMS_SIGNER_INFO decode support\n");
6851         return;
6852     }
6853     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6854      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6855     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6856      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6857      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6858     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6859     if (buf)
6860     {
6861         info = (CMSG_CMS_SIGNER_INFO *)buf;
6862         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6863          info->dwVersion);
6864         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6865          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6866          info->SignerId.dwIdChoice);
6867         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6868          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6869          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6870         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6871          encodedCommonNameNoNull,
6872          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6873          "Unexpected value\n");
6874         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6875          sizeof(serialNum), "Unexpected size %d\n",
6876          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6877         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6878          serialNum, sizeof(serialNum)), "Unexpected value\n");
6879         LocalFree(buf);
6880     }
6881     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6882      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6883      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6884     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6885     if (buf)
6886     {
6887         info = (CMSG_CMS_SIGNER_INFO *)buf;
6888         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6889          info->dwVersion);
6890         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6891          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6892          info->SignerId.dwIdChoice);
6893         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6894          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6895          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6896         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6897          encodedCommonNameNoNull,
6898          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6899          "Unexpected value\n");
6900         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6901          sizeof(serialNum), "Unexpected size %d\n",
6902          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6903         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6904          serialNum, sizeof(serialNum)), "Unexpected value\n");
6905         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6906          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6907         LocalFree(buf);
6908     }
6909     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6910      PKCSSignerWithHashAndEncryptionAlgo,
6911      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6912      NULL, &buf, &size);
6913     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6914     if (buf)
6915     {
6916         info = (CMSG_CMS_SIGNER_INFO *)buf;
6917         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6918          info->dwVersion);
6919         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6920          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6921          info->SignerId.dwIdChoice);
6922         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6923          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6924          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6925         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6926          encodedCommonNameNoNull,
6927          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6928          "Unexpected value\n");
6929         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6930          sizeof(serialNum), "Unexpected size %d\n",
6931          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6932         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6933          serialNum, sizeof(serialNum)), "Unexpected value\n");
6934         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6935          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6936         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6937          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6938         LocalFree(buf);
6939     }
6940     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6941      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6942      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6943     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6944     if (buf)
6945     {
6946         info = (CMSG_CMS_SIGNER_INFO *)buf;
6947         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6948          info->dwVersion);
6949         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6950          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6951          info->SignerId.dwIdChoice);
6952         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6953          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6954          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6955         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6956          encodedCommonNameNoNull,
6957          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6958          "Unexpected value\n");
6959         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6960          sizeof(serialNum), "Unexpected size %d\n",
6961          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6962         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6963          serialNum, sizeof(serialNum)), "Unexpected value\n");
6964         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6965          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6966         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6967          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6968         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6969          info->EncryptedHash.cbData);
6970         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6971          "Unexpected value\n");
6972         LocalFree(buf);
6973     }
6974     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6975      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6976      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6977     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6978     if (buf)
6979     {
6980         info = (CMSG_CMS_SIGNER_INFO *)buf;
6981         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6982          info->dwVersion);
6983         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6984          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6985          info->SignerId.dwIdChoice);
6986         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6987          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6988         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6989          "Unexpected value\n");
6990         LocalFree(buf);
6991     }
6992 }
6993
6994 static BYTE emptyDNSPermittedConstraints[] = {
6995 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6996 static BYTE emptyDNSExcludedConstraints[] = {
6997 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6998 static BYTE DNSExcludedConstraints[] = {
6999 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7000 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7001 static BYTE permittedAndExcludedConstraints[] = {
7002 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7003 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7004 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7005 static BYTE permittedAndExcludedWithMinConstraints[] = {
7006 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7007 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7008 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7009 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7010 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7011 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7012 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7013
7014 static void test_encodeNameConstraints(DWORD dwEncoding)
7015 {
7016     BOOL ret;
7017     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7018     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7019     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7020     LPBYTE buf;
7021     DWORD size;
7022
7023     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7024      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7025     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7026     {
7027         skip("no X509_NAME_CONSTRAINTS encode support\n");
7028         return;
7029     }
7030     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7031     if (ret)
7032     {
7033         ok(size == sizeof(emptySequence), "Unexpected size\n");
7034         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7035         LocalFree(buf);
7036     }
7037     constraints.cPermittedSubtree = 1;
7038     constraints.rgPermittedSubtree = &permitted;
7039     SetLastError(0xdeadbeef);
7040     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7041      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7042     ok(!ret && GetLastError() == E_INVALIDARG,
7043      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7044     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7045     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7046      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7047     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7048     if (ret)
7049     {
7050         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7051         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7052          "Unexpected value\n");
7053         LocalFree(buf);
7054     }
7055     constraints.cPermittedSubtree = 0;
7056     constraints.cExcludedSubtree = 1;
7057     constraints.rgExcludedSubtree = &excluded;
7058     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7059     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7060      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7061     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7062     if (ret)
7063     {
7064         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7065         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7066          "Unexpected value\n");
7067         LocalFree(buf);
7068     }
7069     U(excluded.Base).pwszURL = (LPWSTR)url;
7070     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7071      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7072     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7073     if (ret)
7074     {
7075         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7076         ok(!memcmp(buf, DNSExcludedConstraints, size),
7077          "Unexpected value\n");
7078         LocalFree(buf);
7079     }
7080     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7081     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7082     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7083     constraints.cPermittedSubtree = 1;
7084     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7085      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7086     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7087     if (ret)
7088     {
7089         ok(size == sizeof(permittedAndExcludedConstraints),
7090          "Unexpected size\n");
7091         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7092          "Unexpected value\n");
7093         LocalFree(buf);
7094     }
7095     permitted.dwMinimum = 5;
7096     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7097      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7098     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7099     if (ret)
7100     {
7101         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7102          "Unexpected size\n");
7103         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7104          "Unexpected value\n");
7105         LocalFree(buf);
7106     }
7107     permitted.fMaximum = TRUE;
7108     permitted.dwMaximum = 3;
7109     SetLastError(0xdeadbeef);
7110     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7111      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7112     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7113     if (ret)
7114     {
7115         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7116          "Unexpected size\n");
7117         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7118          "Unexpected value\n");
7119         LocalFree(buf);
7120     }
7121 }
7122
7123 struct EncodedNameConstraints
7124 {
7125     CRYPT_DATA_BLOB            encoded;
7126     CERT_NAME_CONSTRAINTS_INFO constraints;
7127 };
7128
7129 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7130  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7131 static CERT_GENERAL_SUBTREE DNSSubtree = {
7132  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7133 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7134  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7135 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7136  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7137 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7138  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7139
7140 struct EncodedNameConstraints encodedNameConstraints[] = {
7141  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7142  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7143    { 1, &emptyDNSSubtree, 0, NULL } },
7144  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7145    { 0, NULL, 1, &emptyDNSSubtree } },
7146  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7147    { 0, NULL, 1, &DNSSubtree } },
7148  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7149    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7150  { { sizeof(permittedAndExcludedWithMinConstraints),
7151      permittedAndExcludedWithMinConstraints },
7152    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7153  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7154      permittedAndExcludedWithMinMaxConstraints },
7155    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7156 };
7157
7158 static void test_decodeNameConstraints(DWORD dwEncoding)
7159 {
7160     BOOL ret;
7161     DWORD i;
7162     CERT_NAME_CONSTRAINTS_INFO *constraints;
7163
7164     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7165     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7166     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7167     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7168     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7169     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7170     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7171     for (i = 0;
7172      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7173      i++)
7174     {
7175         DWORD size;
7176
7177         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7178          encodedNameConstraints[i].encoded.pbData,
7179          encodedNameConstraints[i].encoded.cbData,
7180          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7181         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7182         {
7183             skip("no X509_NAME_CONSTRAINTS decode support\n");
7184             return;
7185         }
7186         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7187         if (ret)
7188         {
7189             DWORD j;
7190
7191             if (constraints->cPermittedSubtree !=
7192              encodedNameConstraints[i].constraints.cPermittedSubtree)
7193                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7194                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7195                  constraints->cPermittedSubtree);
7196             if (constraints->cPermittedSubtree ==
7197              encodedNameConstraints[i].constraints.cPermittedSubtree)
7198             {
7199                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7200                 {
7201                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7202                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7203                 }
7204             }
7205             if (constraints->cExcludedSubtree !=
7206              encodedNameConstraints[i].constraints.cExcludedSubtree)
7207                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7208                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7209                  constraints->cExcludedSubtree);
7210             if (constraints->cExcludedSubtree ==
7211              encodedNameConstraints[i].constraints.cExcludedSubtree)
7212             {
7213                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7214                 {
7215                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7216                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7217                 }
7218             }
7219             LocalFree(constraints);
7220         }
7221     }
7222 }
7223
7224 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7225  'n','o','t','i','c','e',0 };
7226 static const BYTE noticeWithDisplayText[] = {
7227  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7228  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7229  0x00,0x69,0x00,0x63,0x00,0x65
7230 };
7231 static char org[] = "Wine";
7232 static int noticeNumbers[] = { 2,3 };
7233 static BYTE noticeWithReference[] = {
7234  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7235  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7236  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7237  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7238 };
7239
7240 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7241 {
7242     BOOL ret;
7243     LPBYTE buf;
7244     DWORD size;
7245     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7246     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7247
7248     memset(&notice, 0, sizeof(notice));
7249     ret = pCryptEncodeObjectEx(dwEncoding,
7250      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7251      NULL, &buf, &size);
7252     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7253     {
7254         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7255         return;
7256     }
7257     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7258     if (ret)
7259     {
7260         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7261         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7262         LocalFree(buf);
7263     }
7264     notice.pszDisplayText = noticeText;
7265     ret = pCryptEncodeObjectEx(dwEncoding,
7266      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7267      NULL, &buf, &size);
7268     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7269     if (ret)
7270     {
7271         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7272         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7273         LocalFree(buf);
7274     }
7275     reference.pszOrganization = org;
7276     reference.cNoticeNumbers = 2;
7277     reference.rgNoticeNumbers = noticeNumbers;
7278     notice.pNoticeReference = &reference;
7279     ret = pCryptEncodeObjectEx(dwEncoding,
7280      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7281      NULL, &buf, &size);
7282     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7283     if (ret)
7284     {
7285         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7286         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7287         LocalFree(buf);
7288     }
7289 }
7290
7291 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7292 {
7293     BOOL ret;
7294     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7295     DWORD size;
7296
7297     ret = pCryptDecodeObjectEx(dwEncoding,
7298      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7299      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7300      &notice, &size);
7301     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7302     {
7303         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7304         return;
7305     }
7306     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7307     if (ret)
7308     {
7309         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7310         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7311         LocalFree(notice);
7312     }
7313     ret = pCryptDecodeObjectEx(dwEncoding,
7314      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7315      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7316      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7317     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7318     if (ret)
7319     {
7320         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7321          "unexpected display text\n");
7322         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7323         LocalFree(notice);
7324     }
7325     ret = pCryptDecodeObjectEx(dwEncoding,
7326      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7327      noticeWithReference, sizeof(noticeWithReference),
7328      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7329     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7330     if (ret)
7331     {
7332         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7333          "unexpected display text\n");
7334         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7335         if (notice->pNoticeReference)
7336         {
7337             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7338              "unexpected organization %s\n",
7339              notice->pNoticeReference->pszOrganization);
7340             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7341              "expected 2 notice numbers, got %d\n",
7342              notice->pNoticeReference->cNoticeNumbers);
7343             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7344              "unexpected notice number %d\n",
7345              notice->pNoticeReference->rgNoticeNumbers[0]);
7346             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7347              "unexpected notice number %d\n",
7348              notice->pNoticeReference->rgNoticeNumbers[1]);
7349         }
7350         LocalFree(notice);
7351     }
7352 }
7353
7354 static char oid_any_policy[] = "2.5.29.32.0";
7355 static const BYTE policiesWithAnyPolicy[] = {
7356  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7357 };
7358 static char oid1[] = "1.2.3";
7359 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7360 static const BYTE twoPolicies[] = {
7361  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7362  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7363  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7364  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7365  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7366  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7367 };
7368
7369 static void test_encodeCertPolicies(DWORD dwEncoding)
7370 {
7371     BOOL ret;
7372     CERT_POLICIES_INFO info;
7373     CERT_POLICY_INFO policy[2];
7374     CERT_POLICY_QUALIFIER_INFO qualifier;
7375     LPBYTE buf;
7376     DWORD size;
7377
7378     memset(&info, 0, sizeof(info));
7379     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7380      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7381     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7382     if (ret)
7383     {
7384         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7385         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7386         LocalFree(buf);
7387     }
7388     memset(policy, 0, sizeof(policy));
7389     info.cPolicyInfo = 1;
7390     info.rgPolicyInfo = policy;
7391     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7392      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7393     ok(!ret && (GetLastError() == E_INVALIDARG ||
7394      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7395      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7396     policy[0].pszPolicyIdentifier = oid_any_policy;
7397     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7398      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7399     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7400     if (ret)
7401     {
7402         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7403         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7404         LocalFree(buf);
7405     }
7406     policy[1].pszPolicyIdentifier = oid1;
7407     memset(&qualifier, 0, sizeof(qualifier));
7408     qualifier.pszPolicyQualifierId = oid_user_notice;
7409     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7410     qualifier.Qualifier.pbData = noticeWithReference;
7411     policy[1].cPolicyQualifier = 1;
7412     policy[1].rgPolicyQualifier = &qualifier;
7413     info.cPolicyInfo = 2;
7414     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7415      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7416     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7417     if (ret)
7418     {
7419         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7420         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7421         LocalFree(buf);
7422     }
7423 }
7424
7425 static void test_decodeCertPolicies(DWORD dwEncoding)
7426 {
7427     BOOL ret;
7428     CERT_POLICIES_INFO *info;
7429     DWORD size;
7430
7431     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7432      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7433      &info, &size);
7434     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7435     if (ret)
7436     {
7437         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7438          info->cPolicyInfo);
7439         LocalFree(info);
7440     }
7441     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7442      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7443      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7444     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7445     if (ret)
7446     {
7447         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7448          info->cPolicyInfo);
7449         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7450          "unexpected policy id %s\n",
7451          info->rgPolicyInfo[0].pszPolicyIdentifier);
7452         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7453          "unexpected policy qualifier count %d\n",
7454          info->rgPolicyInfo[0].cPolicyQualifier);
7455         LocalFree(info);
7456     }
7457     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7458      twoPolicies, sizeof(twoPolicies),
7459      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7460     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7461     if (ret)
7462     {
7463         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7464          info->cPolicyInfo);
7465         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7466          "unexpected policy id %s\n",
7467          info->rgPolicyInfo[0].pszPolicyIdentifier);
7468         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7469          "unexpected policy qualifier count %d\n",
7470          info->rgPolicyInfo[0].cPolicyQualifier);
7471         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7472          "unexpected policy id %s\n",
7473          info->rgPolicyInfo[1].pszPolicyIdentifier);
7474         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7475          "unexpected policy qualifier count %d\n",
7476          info->rgPolicyInfo[1].cPolicyQualifier);
7477         ok(!strcmp(
7478          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7479          oid_user_notice), "unexpected policy qualifier id %s\n",
7480          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7481         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7482          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7483          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7484         ok(!memcmp(
7485          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7486          noticeWithReference, sizeof(noticeWithReference)),
7487          "unexpected qualifier value\n");
7488         LocalFree(info);
7489     }
7490 }
7491
7492 static const BYTE policyMappingWithOneMapping[] = {
7493 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7494 static const BYTE policyMappingWithTwoMappings[] = {
7495 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7496 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7497 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7498  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7499
7500 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7501 {
7502     static char oid2[] = "2.3.4";
7503     static char oid3[] = "1.3.4";
7504     static char oid4[] = "2.5.6";
7505     BOOL ret;
7506     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7507     CERT_POLICY_MAPPING mapping[2];
7508     LPBYTE buf;
7509     DWORD size, i;
7510
7511     /* Each of the mapping OIDs is equivalent, so check with all of them */
7512     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7513     {
7514         memset(&info, 0, sizeof(info));
7515         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7516          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7517         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7518          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7519         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7520         {
7521             win_skip("no policy mappings support\n");
7522             return;
7523         }
7524         if (ret)
7525         {
7526             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7527             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7528              "unexpected value\n");
7529             LocalFree(buf);
7530         }
7531         mapping[0].pszIssuerDomainPolicy = NULL;
7532         mapping[0].pszSubjectDomainPolicy = NULL;
7533         info.cPolicyMapping = 1;
7534         info.rgPolicyMapping = mapping;
7535         SetLastError(0xdeadbeef);
7536         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7537          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7538         ok(!ret && GetLastError() == E_INVALIDARG,
7539          "expected E_INVALIDARG, got %08x\n", GetLastError());
7540         mapping[0].pszIssuerDomainPolicy = oid1;
7541         mapping[0].pszSubjectDomainPolicy = oid2;
7542         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7543          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7544         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7545         if (ret)
7546         {
7547             ok(size == sizeof(policyMappingWithOneMapping),
7548              "unexpected size %d\n", size);
7549             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7550              "unexpected value\n");
7551             LocalFree(buf);
7552         }
7553         mapping[1].pszIssuerDomainPolicy = oid3;
7554         mapping[1].pszSubjectDomainPolicy = oid4;
7555         info.cPolicyMapping = 2;
7556         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7557          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7558         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7559         if (ret)
7560         {
7561             ok(size == sizeof(policyMappingWithTwoMappings),
7562              "unexpected size %d\n", size);
7563             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7564              "unexpected value\n");
7565             LocalFree(buf);
7566         }
7567     }
7568 }
7569
7570 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7571 {
7572     DWORD size, i;
7573     CERT_POLICY_MAPPINGS_INFO *info;
7574     BOOL ret;
7575
7576     /* Each of the mapping OIDs is equivalent, so check with all of them */
7577     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7578     {
7579         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7580          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7581          &info, &size);
7582         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7583          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7584         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7585         {
7586             win_skip("no policy mappings support\n");
7587             return;
7588         }
7589         if (ret)
7590         {
7591             ok(info->cPolicyMapping == 0,
7592              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7593             LocalFree(info);
7594         }
7595         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7596          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7597          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7598         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7599         if (ret)
7600         {
7601             ok(info->cPolicyMapping == 1,
7602              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7603             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7604              "unexpected issuer policy %s\n",
7605              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7606             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7607              "2.3.4"), "unexpected subject policy %s\n",
7608              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7609             LocalFree(info);
7610         }
7611         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7612          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7613          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7614         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7615         if (ret)
7616         {
7617             ok(info->cPolicyMapping == 2,
7618              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7619             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7620              "unexpected issuer policy %s\n",
7621              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7622             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7623              "2.3.4"), "unexpected subject policy %s\n",
7624              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7625             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7626              "unexpected issuer policy %s\n",
7627              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7628             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7629              "2.5.6"), "unexpected subject policy %s\n",
7630              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7631             LocalFree(info);
7632         }
7633     }
7634 }
7635
7636 static const BYTE policyConstraintsWithRequireExplicit[] = {
7637 0x30,0x03,0x80,0x01,0x00 };
7638 static const BYTE policyConstraintsWithInhibitMapping[] = {
7639 0x30,0x03,0x81,0x01,0x01 };
7640 static const BYTE policyConstraintsWithBoth[] = {
7641 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7642
7643 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7644 {
7645     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7646     LPBYTE buf;
7647     DWORD size;
7648     BOOL ret;
7649
7650     /* Even though RFC 5280 explicitly states CAs must not issue empty
7651      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7652      */
7653     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7654      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7655     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7656      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7657     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7658     {
7659         win_skip("no policy constraints support\n");
7660         return;
7661     }
7662     if (ret)
7663     {
7664         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7665         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7666          "unexpected value\n");
7667         LocalFree(buf);
7668     }
7669     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7670      * is not, then a skip of 0 is encoded.
7671      */
7672     info.fRequireExplicitPolicy = TRUE;
7673     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7674      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7675     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7676     if (ret)
7677     {
7678         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7679          "unexpected size %d\n", size);
7680         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7681          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7682         LocalFree(buf);
7683     }
7684     /* With inhibit policy mapping */
7685     info.fRequireExplicitPolicy = FALSE;
7686     info.dwRequireExplicitPolicySkipCerts = 0;
7687     info.fInhibitPolicyMapping = TRUE;
7688     info.dwInhibitPolicyMappingSkipCerts = 1;
7689     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7690      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7691     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7692     if (ret)
7693     {
7694         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7695          "unexpected size %d\n", size);
7696         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7697          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7698         LocalFree(buf);
7699     }
7700     /* And with both */
7701     info.fRequireExplicitPolicy = TRUE;
7702     info.dwRequireExplicitPolicySkipCerts = 1;
7703     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7704      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7705     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7706     if (ret)
7707     {
7708         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7709          size);
7710         ok(!memcmp(buf, policyConstraintsWithBoth,
7711          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7712         LocalFree(buf);
7713     }
7714 }
7715
7716 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7717 {
7718     CERT_POLICY_CONSTRAINTS_INFO *info;
7719     DWORD size;
7720     BOOL ret;
7721
7722     /* Again, even though CAs must not issue such constraints, they can be
7723      * decoded.
7724      */
7725     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7726      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7727      &info, &size);
7728     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7729      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7730     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7731     {
7732         win_skip("no policy mappings support\n");
7733         return;
7734     }
7735     if (ret)
7736     {
7737         ok(!info->fRequireExplicitPolicy,
7738          "expected require explicit = FALSE\n");
7739         ok(!info->fInhibitPolicyMapping,
7740          "expected implicit mapping = FALSE\n");
7741         LocalFree(info);
7742     }
7743     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7744      policyConstraintsWithRequireExplicit,
7745      sizeof(policyConstraintsWithRequireExplicit), 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 = TRUE\n");
7752         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7753          info->dwRequireExplicitPolicySkipCerts);
7754         ok(!info->fInhibitPolicyMapping,
7755          "expected implicit mapping = FALSE\n");
7756         LocalFree(info);
7757     }
7758     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7759      policyConstraintsWithInhibitMapping,
7760      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7761      NULL, &info, &size);
7762     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7763     if (ret)
7764     {
7765         ok(!info->fRequireExplicitPolicy,
7766          "expected require explicit = FALSE\n");
7767         ok(info->fInhibitPolicyMapping,
7768          "expected implicit mapping = TRUE\n");
7769         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7770          info->dwInhibitPolicyMappingSkipCerts);
7771         LocalFree(info);
7772     }
7773     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7774      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7775      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7776     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7777     if (ret)
7778     {
7779         ok(info->fRequireExplicitPolicy,
7780          "expected require explicit = TRUE\n");
7781         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7782          info->dwRequireExplicitPolicySkipCerts);
7783         ok(info->fInhibitPolicyMapping,
7784          "expected implicit mapping = TRUE\n");
7785         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7786          info->dwInhibitPolicyMappingSkipCerts);
7787         LocalFree(info);
7788     }
7789 }
7790
7791 /* Free *pInfo with HeapFree */
7792 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7793 {
7794     BOOL ret;
7795     DWORD size = 0;
7796     HCRYPTKEY key;
7797
7798     /* This crashes
7799     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7800      */
7801     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7802     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7803      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7804     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7805      &size);
7806     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7807      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7808     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7809      NULL, &size);
7810     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7811      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7812     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7813      0, NULL, NULL, &size);
7814     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7815      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7816     /* Test with no key */
7817     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7818      0, NULL, NULL, &size);
7819     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7820      GetLastError());
7821     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7822     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7823     if (ret)
7824     {
7825         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7826          NULL, 0, NULL, NULL, &size);
7827         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7828         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7829         if (*pInfo)
7830         {
7831             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7832              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7833             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7834              GetLastError());
7835             if (ret)
7836             {
7837                 /* By default (we passed NULL as the OID) the OID is
7838                  * szOID_RSA_RSA.
7839                  */
7840                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7841                  "Expected %s, got %s\n", szOID_RSA_RSA,
7842                  (*pInfo)->Algorithm.pszObjId);
7843             }
7844         }
7845     }
7846     CryptDestroyKey(key);
7847 }
7848
7849 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7850  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7851  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7852  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7853  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7854  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7855  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7856  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7857  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7858  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7859  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7860  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7861  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7862  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7863  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7864  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7865  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7866  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7867  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7868  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7869  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7870  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7871  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7872  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7873  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7874
7875 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7876 {
7877     BOOL ret;
7878     HCRYPTKEY key;
7879     PCCERT_CONTEXT context;
7880     DWORD dwSize;
7881     ALG_ID ai;
7882
7883     /* These crash
7884     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7885     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7886     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7887     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7888      NULL);
7889      */
7890     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7891     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7892      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7893     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7894     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7895      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7896     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7897      &key);
7898     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7899      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7900
7901     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7902     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7903      &key);
7904     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7905
7906     dwSize = sizeof(ai);
7907     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7908     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7909     if(ret)
7910     {
7911       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7912       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7913     }
7914
7915     CryptDestroyKey(key);
7916
7917     /* Repeat with forced algorithm */
7918     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7919      &key);
7920     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7921
7922     dwSize = sizeof(ai);
7923     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7924     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7925     if(ret)
7926     {
7927       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7928       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7929     }
7930
7931     CryptDestroyKey(key);
7932
7933     /* Test importing a public key from a certificate context */
7934     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7935      sizeof(expiredCert));
7936     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7937      GetLastError());
7938     if (context)
7939     {
7940         ok(!strcmp(szOID_RSA_RSA,
7941          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7942          "Expected %s, got %s\n", szOID_RSA_RSA,
7943          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7944         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7945          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7946         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7947         CryptDestroyKey(key);
7948         CertFreeCertificateContext(context);
7949     }
7950 }
7951
7952 static const char cspName[] = "WineCryptTemp";
7953
7954 static void testPortPublicKeyInfo(void)
7955 {
7956     HCRYPTPROV csp;
7957     BOOL ret;
7958     PCERT_PUBLIC_KEY_INFO info = NULL;
7959
7960     /* Just in case a previous run failed, delete this thing */
7961     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7962      CRYPT_DELETEKEYSET);
7963     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7964      CRYPT_NEWKEYSET);
7965     ok(ret,"CryptAcquireContextA failed\n");
7966
7967     testExportPublicKey(csp, &info);
7968     testImportPublicKey(csp, info);
7969
7970     HeapFree(GetProcessHeap(), 0, info);
7971     CryptReleaseContext(csp, 0);
7972     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7973      CRYPT_DELETEKEYSET);
7974     ok(ret,"CryptAcquireContextA failed\n");
7975 }
7976
7977 START_TEST(encode)
7978 {
7979     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7980      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7981     HMODULE hCrypt32;
7982     DWORD i;
7983
7984     hCrypt32 = GetModuleHandleA("crypt32.dll");
7985     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7986     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7987     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7988     {
7989         win_skip("CryptDecodeObjectEx() is not available\n");
7990         return;
7991     }
7992
7993     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7994     {
7995         test_encodeInt(encodings[i]);
7996         test_decodeInt(encodings[i]);
7997         test_encodeEnumerated(encodings[i]);
7998         test_decodeEnumerated(encodings[i]);
7999         test_encodeFiletime(encodings[i]);
8000         test_decodeFiletime(encodings[i]);
8001         test_encodeName(encodings[i]);
8002         test_decodeName(encodings[i]);
8003         test_encodeUnicodeName(encodings[i]);
8004         test_decodeUnicodeName(encodings[i]);
8005         test_encodeNameValue(encodings[i]);
8006         test_decodeNameValue(encodings[i]);
8007         test_encodeUnicodeNameValue(encodings[i]);
8008         test_decodeUnicodeNameValue(encodings[i]);
8009         test_encodeAltName(encodings[i]);
8010         test_decodeAltName(encodings[i]);
8011         test_encodeOctets(encodings[i]);
8012         test_decodeOctets(encodings[i]);
8013         test_encodeBits(encodings[i]);
8014         test_decodeBits(encodings[i]);
8015         test_encodeBasicConstraints(encodings[i]);
8016         test_decodeBasicConstraints(encodings[i]);
8017         test_encodeRsaPublicKey(encodings[i]);
8018         test_decodeRsaPublicKey(encodings[i]);
8019         test_encodeSequenceOfAny(encodings[i]);
8020         test_decodeSequenceOfAny(encodings[i]);
8021         test_encodeExtensions(encodings[i]);
8022         test_decodeExtensions(encodings[i]);
8023         test_encodePublicKeyInfo(encodings[i]);
8024         test_decodePublicKeyInfo(encodings[i]);
8025         test_encodeCertToBeSigned(encodings[i]);
8026         test_decodeCertToBeSigned(encodings[i]);
8027         test_encodeCert(encodings[i]);
8028         test_decodeCert(encodings[i]);
8029         test_encodeCRLDistPoints(encodings[i]);
8030         test_decodeCRLDistPoints(encodings[i]);
8031         test_encodeCRLIssuingDistPoint(encodings[i]);
8032         test_decodeCRLIssuingDistPoint(encodings[i]);
8033         test_encodeCRLToBeSigned(encodings[i]);
8034         test_decodeCRLToBeSigned(encodings[i]);
8035         test_encodeEnhancedKeyUsage(encodings[i]);
8036         test_decodeEnhancedKeyUsage(encodings[i]);
8037         test_encodeAuthorityKeyId(encodings[i]);
8038         test_decodeAuthorityKeyId(encodings[i]);
8039         test_encodeAuthorityKeyId2(encodings[i]);
8040         test_decodeAuthorityKeyId2(encodings[i]);
8041         test_encodeAuthorityInfoAccess(encodings[i]);
8042         test_decodeAuthorityInfoAccess(encodings[i]);
8043         test_encodeCTL(encodings[i]);
8044         test_decodeCTL(encodings[i]);
8045         test_encodePKCSContentInfo(encodings[i]);
8046         test_decodePKCSContentInfo(encodings[i]);
8047         test_encodePKCSAttribute(encodings[i]);
8048         test_decodePKCSAttribute(encodings[i]);
8049         test_encodePKCSAttributes(encodings[i]);
8050         test_decodePKCSAttributes(encodings[i]);
8051         test_encodePKCSSMimeCapabilities(encodings[i]);
8052         test_decodePKCSSMimeCapabilities(encodings[i]);
8053         test_encodePKCSSignerInfo(encodings[i]);
8054         test_decodePKCSSignerInfo(encodings[i]);
8055         test_encodeCMSSignerInfo(encodings[i]);
8056         test_decodeCMSSignerInfo(encodings[i]);
8057         test_encodeNameConstraints(encodings[i]);
8058         test_decodeNameConstraints(encodings[i]);
8059         test_encodePolicyQualifierUserNotice(encodings[i]);
8060         test_decodePolicyQualifierUserNotice(encodings[i]);
8061         test_encodeCertPolicies(encodings[i]);
8062         test_decodeCertPolicies(encodings[i]);
8063         test_encodeCertPolicyMappings(encodings[i]);
8064         test_decodeCertPolicyMappings(encodings[i]);
8065         test_encodeCertPolicyConstraints(encodings[i]);
8066         test_decodeCertPolicyConstraints(encodings[i]);
8067     }
8068     testPortPublicKeyInfo();
8069 }