rsaenh: Fix padding bytes check for 0-byte payload.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (buf)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (buf)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (buf)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (buf)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (buf)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (buf)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              &val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (buf)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666            broken(ret), /* Win9x and NT4 for bin38 */
667          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668          GetLastError());
669     }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690  0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692  0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694  0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698  0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[]            = "2.5.4.6",
706             oid_minnesota[]     = "2.5.4.8",
707             oid_minneapolis[]   = "2.5.4.7",
708             oid_codeweavers[]   = "2.5.4.10",
709             oid_wine[]          = "2.5.4.11",
710             oid_localhostAttr[] = "2.5.4.3",
711             oid_aric[]          = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713                                     { RDNA(minnesota) },
714                                     { RDNA(minneapolis) },
715                                     { RDNA(codeweavers) },
716                                     { RDNA(wine) },
717                                     { RDNA(localhostAttr) },
718                                     { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720                                            { RDNA(localhostAttr) },
721                                            { RDNA(minnesota) },
722                                            { RDNA(minneapolis) },
723                                            { RDNA(codeweavers) },
724                                            { RDNA(wine) },
725                                            { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745     CERT_RDN_ATTR attrs[2];
746     CERT_RDN rdn;
747     CERT_NAME_INFO info;
748     static CHAR oid_common_name[] = szOID_COMMON_NAME,
749                 oid_sur_name[]    = szOID_SUR_NAME;
750     BYTE *buf = NULL;
751     DWORD size = 0;
752     BOOL ret;
753
754     if (0)
755     {
756         /* Test with NULL pvStructInfo (crashes on win9x) */
757         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761     }
762     /* Test with empty CERT_NAME_INFO */
763     info.cRDN = 0;
764     info.rgRDN = NULL;
765     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (buf)
769     {
770         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771          "Got unexpected encoding for empty name\n");
772         LocalFree(buf);
773     }
774     if (0)
775     {
776         /* Test with bogus CERT_RDN (crashes on win9x) */
777         info.cRDN = 1;
778         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782     }
783     /* Test with empty CERT_RDN */
784     rdn.cRDNAttr = 0;
785     rdn.rgRDNAttr = NULL;
786     info.cRDN = 1;
787     info.rgRDN = &rdn;
788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791     if (buf)
792     {
793         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794          "Got unexpected encoding for empty RDN array\n");
795         LocalFree(buf);
796     }
797     if (0)
798     {
799         /* Test with bogus attr array (crashes on win9x) */
800         rdn.cRDNAttr = 1;
801         rdn.rgRDNAttr = NULL;
802         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806     }
807     /* oddly, a bogus OID is accepted by Windows XP; not testing.
808     attrs[0].pszObjId = "bogus";
809     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810     attrs[0].Value.cbData = sizeof(commonName);
811     attrs[0].Value.pbData = commonName;
812     rdn.cRDNAttr = 1;
813     rdn.rgRDNAttr = attrs;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816     ok(!ret, "Expected failure, got success\n");
817      */
818     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
819      * the encoded attributes to be swapped.
820      */
821     attrs[0].pszObjId = oid_common_name;
822     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823     attrs[0].Value.cbData = sizeof(commonName);
824     attrs[0].Value.pbData = (BYTE *)commonName;
825     attrs[1].pszObjId = oid_sur_name;
826     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827     attrs[1].Value.cbData = sizeof(surName);
828     attrs[1].Value.pbData = (BYTE *)surName;
829     rdn.cRDNAttr = 2;
830     rdn.rgRDNAttr = attrs;
831     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834     if (buf)
835     {
836         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837          "Got unexpected encoding for two RDN array\n");
838         LocalFree(buf);
839     }
840     /* A name can be "encoded" with previously encoded RDN attrs. */
841     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843     attrs[0].Value.cbData = sizeof(twoRDNs);
844     rdn.cRDNAttr = 1;
845     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848     if (buf)
849     {
850         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851         ok(!memcmp(buf, encodedTwoRDNs, size),
852          "Unexpected value for re-endoded two RDN array\n");
853         LocalFree(buf);
854     }
855     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856     rdn.cRDNAttr = 1;
857     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860     ok(!ret && GetLastError() == E_INVALIDARG,
861      "Expected E_INVALIDARG, got %08x\n", GetLastError());
862     /* Test a more complex name */
863     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864     rdn.rgRDNAttr = rdnAttrs;
865     info.cRDN = 1;
866     info.rgRDN = &rdn;
867     buf = NULL;
868     size = 0;
869     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872     if (ret)
873     {
874         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876         LocalFree(buf);
877     }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886  0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891  0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895     CERT_RDN_ATTR attrs[2];
896     CERT_RDN rdn;
897     CERT_NAME_INFO info;
898     static CHAR oid_common_name[] = szOID_COMMON_NAME,
899                 oid_sur_name[]    = szOID_SUR_NAME;
900     BYTE *buf = NULL;
901     DWORD size = 0;
902     BOOL ret;
903
904     if (0)
905     {
906         /* Test with NULL pvStructInfo (crashes on win9x) */
907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911     }
912     /* Test with empty CERT_NAME_INFO */
913     info.cRDN = 0;
914     info.rgRDN = NULL;
915     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918     if (buf)
919     {
920         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921          "Got unexpected encoding for empty name\n");
922         LocalFree(buf);
923     }
924     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925      * encoding (the NULL).
926      */
927     attrs[0].pszObjId = oid_common_name;
928     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929     attrs[0].Value.cbData = sizeof(commonNameW);
930     attrs[0].Value.pbData = (BYTE *)commonNameW;
931     rdn.cRDNAttr = 1;
932     rdn.rgRDNAttr = attrs;
933     info.cRDN = 1;
934     info.rgRDN = &rdn;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939     ok(size == 9, "Unexpected error index %08x\n", size);
940     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
941      * forces the order of the encoded attributes to be swapped.
942      */
943     attrs[0].pszObjId = oid_common_name;
944     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945     attrs[0].Value.cbData = 0;
946     attrs[0].Value.pbData = (BYTE *)commonNameW;
947     attrs[1].pszObjId = oid_sur_name;
948     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949     attrs[1].Value.cbData = 0;
950     attrs[1].Value.pbData = (BYTE *)surNameW;
951     rdn.cRDNAttr = 2;
952     rdn.rgRDNAttr = attrs;
953     info.cRDN = 1;
954     info.rgRDN = &rdn;
955     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958     if (buf)
959     {
960         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961          "Got unexpected encoding for two RDN array\n");
962         LocalFree(buf);
963     }
964     /* A name can be "encoded" with previously encoded RDN attrs. */
965     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967     attrs[0].Value.cbData = sizeof(twoRDNs);
968     rdn.cRDNAttr = 1;
969     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972     if (buf)
973     {
974         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975         ok(!memcmp(buf, encodedTwoRDNs, size),
976          "Unexpected value for re-endoded two RDN array\n");
977         LocalFree(buf);
978     }
979     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980     rdn.cRDNAttr = 1;
981     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985     if (buf)
986     {
987         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989         LocalFree(buf);
990     }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994  const CERT_NAME_VALUE *got)
995 {
996     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997         got->dwValueType == CERT_RDN_ENCODED_BLOB)
998     {
999         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000         return;
1001     }
1002
1003     ok(got->dwValueType == expected->dwValueType,
1004      "Expected string type %d, got %d\n", expected->dwValueType,
1005      got->dwValueType);
1006     ok(got->Value.cbData == expected->Value.cbData,
1007      "String type %d: unexpected data size, got %d, expected %d\n",
1008      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009     if (got->Value.cbData && got->Value.pbData)
1010         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011          min(got->Value.cbData, expected->Value.cbData)),
1012          "String type %d: unexpected value\n", expected->dwValueType);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016  const CERT_RDN_ATTR *got)
1017 {
1018     if (expected->pszObjId && strlen(expected->pszObjId))
1019     {
1020         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021          expected->pszObjId);
1022         if (got->pszObjId)
1023         {
1024             ok(!strcmp(got->pszObjId, expected->pszObjId),
1025              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026              expected->pszObjId);
1027         }
1028     }
1029     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030      (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035     ok(got->cRDNAttr == expected->cRDNAttr,
1036      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037     if (got->cRDNAttr)
1038     {
1039         DWORD i;
1040
1041         for (i = 0; i < got->cRDNAttr; i++)
1042             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043     }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047  const CERT_NAME_INFO *got)
1048 {
1049     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050      expected->cRDN, got->cRDN);
1051     if (got->cRDN)
1052     {
1053         DWORD i;
1054
1055         for (i = 0; i < got->cRDN; i++)
1056             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057     }
1058 }
1059
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068     BYTE *buf = NULL;
1069     DWORD bufSize = 0;
1070     BOOL ret;
1071     CERT_RDN rdn;
1072     CERT_NAME_INFO info = { 1, &rdn };
1073
1074     /* test empty name */
1075     bufSize = 0;
1076     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077      emptySequence[1] + 2,
1078      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079      &buf, &bufSize);
1080     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1082      * decoder works the same way, so only test the count.
1083      */
1084     if (buf)
1085     {
1086         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088          "Expected 0 RDNs in empty info, got %d\n",
1089          ((CERT_NAME_INFO *)buf)->cRDN);
1090         LocalFree(buf);
1091     }
1092     /* test empty name with indefinite-length encoding */
1093     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095      &buf, &bufSize);
1096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097     if (ret)
1098     {
1099         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101          "Expected 0 RDNs in empty info, got %d\n",
1102          ((CERT_NAME_INFO *)buf)->cRDN);
1103         LocalFree(buf);
1104     }
1105     /* test empty RDN */
1106     bufSize = 0;
1107     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108      emptyRDNs[1] + 2,
1109      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110      &buf, &bufSize);
1111     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112     if (buf)
1113     {
1114         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
1116         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118          "Got unexpected value for empty RDN\n");
1119         LocalFree(buf);
1120     }
1121     /* test two RDN attrs */
1122     bufSize = 0;
1123     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124      twoRDNs[1] + 2,
1125      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126      &buf, &bufSize);
1127     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128     if (buf)
1129     {
1130         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1131                     oid_common_name[] = szOID_COMMON_NAME;
1132
1133         CERT_RDN_ATTR attrs[] = {
1134          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135           (BYTE *)surName } },
1136          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137           (BYTE *)commonName } },
1138         };
1139
1140         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141         rdn.rgRDNAttr = attrs;
1142         compareNames(&info, (CERT_NAME_INFO *)buf);
1143         LocalFree(buf);
1144     }
1145     /* test that two RDN attrs with extra bytes succeeds */
1146     bufSize = 0;
1147     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150     /* And, a slightly more complicated name */
1151     buf = NULL;
1152     bufSize = 0;
1153     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156     if (ret)
1157     {
1158         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159         rdn.rgRDNAttr = decodedRdnAttrs;
1160         compareNames(&info, (CERT_NAME_INFO *)buf);
1161         LocalFree(buf);
1162     }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167     BYTE *buf = NULL;
1168     DWORD bufSize = 0;
1169     BOOL ret;
1170     CERT_RDN rdn;
1171     CERT_NAME_INFO info = { 1, &rdn };
1172
1173     /* test empty name */
1174     bufSize = 0;
1175     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176      emptySequence[1] + 2,
1177      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178      &buf, &bufSize);
1179     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180     if (buf)
1181     {
1182         ok(bufSize == sizeof(CERT_NAME_INFO),
1183          "Got wrong bufSize %d\n", bufSize);
1184         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185          "Expected 0 RDNs in empty info, got %d\n",
1186          ((CERT_NAME_INFO *)buf)->cRDN);
1187         LocalFree(buf);
1188     }
1189     /* test empty RDN */
1190     bufSize = 0;
1191     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192      emptyRDNs[1] + 2,
1193      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194      &buf, &bufSize);
1195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196     if (buf)
1197     {
1198         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
1200         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202          "Got unexpected value for empty RDN\n");
1203         LocalFree(buf);
1204     }
1205     /* test two RDN attrs */
1206     bufSize = 0;
1207     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208      sizeof(twoRDNsNoNull),
1209      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210      &buf, &bufSize);
1211     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212     if (buf)
1213     {
1214         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1215                     oid_common_name[] = szOID_COMMON_NAME;
1216
1217         CERT_RDN_ATTR attrs[] = {
1218          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1222         };
1223
1224         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225         rdn.rgRDNAttr = attrs;
1226         compareNames(&info, (CERT_NAME_INFO *)buf);
1227         LocalFree(buf);
1228     }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233     CERT_NAME_VALUE value;
1234     const BYTE *encoded;
1235     DWORD encodedSize;
1236 };
1237
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1267 static char embedded_null[] = "foo\0com";
1268 static BYTE ia5EmbeddedNull[] = {
1269  0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1270
1271 static struct EncodedNameValue nameValues[] = {
1272  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273      octetCommonNameValue, sizeof(octetCommonNameValue) },
1274  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      numericCommonNameValue, sizeof(numericCommonNameValue) },
1276  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      printableCommonNameValue, sizeof(printableCommonNameValue) },
1278  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      t61CommonNameValue, sizeof(t61CommonNameValue) },
1280  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1282  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1284  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1286  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1288  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289      generalCommonNameValue, sizeof(generalCommonNameValue) },
1290  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1291      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1292  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1294  /* The following tests succeed under Windows, but really should fail,
1295   * they contain characters that are illegal for the encoding.  I'm
1296   * including them to justify my lazy encoding.
1297   */
1298  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1299      sizeof(bin42) },
1300  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1301      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1302  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1303      bin44, sizeof(bin44) },
1304 };
1305 /* This is kept separate, because the decoding doesn't return to the original
1306  * value.
1307  */
1308 static struct EncodedNameValue embeddedNullNameValue = {
1309  { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1310    ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1311
1312 static void test_encodeNameValue(DWORD dwEncoding)
1313 {
1314     BYTE *buf = NULL;
1315     DWORD size = 0, i;
1316     BOOL ret;
1317     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1318
1319     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1320     value.Value.pbData = printableCommonNameValue;
1321     value.Value.cbData = sizeof(printableCommonNameValue);
1322     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1323      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1324     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1325     if (buf)
1326     {
1327         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1328          size);
1329         ok(!memcmp(buf, printableCommonNameValue, size),
1330          "Unexpected encoding\n");
1331         LocalFree(buf);
1332     }
1333     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1334     {
1335         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1336          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1337         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1338          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1339          nameValues[i].value.dwValueType, GetLastError());
1340         if (ret)
1341         {
1342             ok(size == nameValues[i].encodedSize,
1343              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1344             ok(!memcmp(buf, nameValues[i].encoded, size),
1345              "Got unexpected encoding\n");
1346             LocalFree(buf);
1347         }
1348     }
1349     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1350      &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1351     ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1352      "Type %d: CryptEncodeObjectEx failed: %08x\n",
1353      embeddedNullNameValue.value.dwValueType, GetLastError());
1354     if (ret)
1355     {
1356         ok(size == embeddedNullNameValue.encodedSize,
1357          "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1358         ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1359          "Got unexpected encoding\n");
1360         LocalFree(buf);
1361     }
1362 }
1363
1364 static void test_decodeNameValue(DWORD dwEncoding)
1365 {
1366     int i;
1367     BYTE *buf = NULL;
1368     DWORD bufSize = 0;
1369     BOOL ret;
1370
1371     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1372     {
1373         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1374          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1375          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1376          &buf, &bufSize);
1377         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1378          nameValues[i].value.dwValueType, GetLastError());
1379         if (ret)
1380         {
1381             compareNameValues(&nameValues[i].value,
1382              (const CERT_NAME_VALUE *)buf);
1383             LocalFree(buf);
1384         }
1385     }
1386     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1387      embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1388      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1389      &buf, &bufSize);
1390     ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1391      embeddedNullNameValue.value.dwValueType, GetLastError());
1392     if (ret)
1393     {
1394         CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1395          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1396         CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1397          { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1398         const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1399          *expected = NULL;
1400
1401         /* Some Windows versions decode name values with embedded NULLs,
1402          * others leave them encoded, even with the same version of crypt32.
1403          * Accept either.
1404          */
1405         ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1406          got->dwValueType == CERT_RDN_IA5_STRING,
1407          "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1408          got->dwValueType);
1409         if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1410             expected = &rdnEncodedValue;
1411         else if (got->dwValueType == CERT_RDN_IA5_STRING)
1412             expected = &embeddedNullValue;
1413         if (expected)
1414         {
1415             ok(got->Value.cbData == expected->Value.cbData,
1416              "String type %d: unexpected data size, got %d, expected %d\n",
1417              got->dwValueType, got->Value.cbData, expected->Value.cbData);
1418             if (got->Value.cbData && got->Value.pbData)
1419                 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1420                  min(got->Value.cbData, expected->Value.cbData)),
1421                  "String type %d: unexpected value\n", expected->dwValueType);
1422         }
1423         LocalFree(buf);
1424     }
1425 }
1426
1427 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1428 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1429 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1430  'h','q','.','o','r','g',0 };
1431 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1432  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1433  0x6f, 0x72, 0x67 };
1434 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1435  0x575b, 0 };
1436 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1437 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1438  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1439 static const BYTE localhost[] = { 127, 0, 0, 1 };
1440 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1441  0x01 };
1442 static const unsigned char encodedCommonName[] = {
1443     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1444 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1445 static const BYTE encodedDirectoryName[] = {
1446 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1447 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1448
1449 static void test_encodeAltName(DWORD dwEncoding)
1450 {
1451     CERT_ALT_NAME_INFO info = { 0 };
1452     CERT_ALT_NAME_ENTRY entry = { 0 };
1453     BYTE *buf = NULL;
1454     DWORD size = 0;
1455     BOOL ret;
1456     char oid[] = "1.2.3";
1457
1458     /* Test with empty info */
1459     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1460      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1461     if (buf)
1462     {
1463         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1464         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1465         LocalFree(buf);
1466     }
1467     /* Test with an empty entry */
1468     info.cAltEntry = 1;
1469     info.rgAltEntry = &entry;
1470     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1471      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1472     ok(!ret && GetLastError() == E_INVALIDARG,
1473      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1474     /* Test with an empty pointer */
1475     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1476     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1477      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1478     if (buf)
1479     {
1480         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1481         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1482         LocalFree(buf);
1483     }
1484     /* Test with a real URL */
1485     U(entry).pwszURL = (LPWSTR)url;
1486     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1487      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1488     if (buf)
1489     {
1490         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1491         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1492         LocalFree(buf);
1493     }
1494     /* Now with the URL containing an invalid IA5 char */
1495     U(entry).pwszURL = (LPWSTR)nihongoURL;
1496     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1497      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1498     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1499      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1500     /* The first invalid character is at index 7 */
1501     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1502      "Expected invalid char at index 7, got %d\n",
1503      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1504     /* Now with the URL missing a scheme */
1505     U(entry).pwszURL = (LPWSTR)dnsName;
1506     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1507      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1508     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1509     if (buf)
1510     {
1511         /* This succeeds, but it shouldn't, so don't worry about conforming */
1512         LocalFree(buf);
1513     }
1514     /* Now with a DNS name */
1515     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1516     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1517      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1518     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1519     if (buf)
1520     {
1521         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1522         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1523         LocalFree(buf);
1524     }
1525     /* Test with an IP address */
1526     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1527     U(entry).IPAddress.cbData = sizeof(localhost);
1528     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1529     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1530      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1531     if (buf)
1532     {
1533         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1534         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1535         LocalFree(buf);
1536     }
1537     /* Test with OID */
1538     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1539     U(entry).pszRegisteredID = oid;
1540     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1541      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1542     if (buf)
1543     {
1544         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1545         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1546         LocalFree(buf);
1547     }
1548     /* Test with directory name */
1549     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1550     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1551     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1552     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1553      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1554     if (buf)
1555     {
1556         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1557         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1558         LocalFree(buf);
1559     }
1560 }
1561
1562 static void test_decodeAltName(DWORD dwEncoding)
1563 {
1564     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1565      0x00, 0x00, 0x01 };
1566     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1567      0x01 };
1568     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1569      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1570     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1571      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1572     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1573      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1574     BOOL ret;
1575     BYTE *buf = NULL;
1576     DWORD bufSize = 0;
1577     CERT_ALT_NAME_INFO *info;
1578
1579     /* Test some bogus ones first */
1580     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1581      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1582      NULL, &buf, &bufSize);
1583     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1584      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1585      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1586      GetLastError());
1587     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1588      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1589      &bufSize);
1590     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1591      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1592      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1593      GetLastError());
1594     /* Now expected cases */
1595     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1596      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1597     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1598     if (buf)
1599     {
1600         info = (CERT_ALT_NAME_INFO *)buf;
1601
1602         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1603          info->cAltEntry);
1604         LocalFree(buf);
1605     }
1606     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1607      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1608     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1609     if (buf)
1610     {
1611         info = (CERT_ALT_NAME_INFO *)buf;
1612
1613         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1614          info->cAltEntry);
1615         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1616          "Expected CERT_ALT_NAME_URL, got %d\n",
1617          info->rgAltEntry[0].dwAltNameChoice);
1618         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1619          "Expected empty URL\n");
1620         LocalFree(buf);
1621     }
1622     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1623      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1624     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1625     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1626      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628     if (buf)
1629     {
1630         info = (CERT_ALT_NAME_INFO *)buf;
1631
1632         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633          info->cAltEntry);
1634         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1635          "Expected CERT_ALT_NAME_URL, got %d\n",
1636          info->rgAltEntry[0].dwAltNameChoice);
1637         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1638         LocalFree(buf);
1639     }
1640     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1641      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1642     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1643     if (buf)
1644     {
1645         info = (CERT_ALT_NAME_INFO *)buf;
1646
1647         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1648          info->cAltEntry);
1649         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1650          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1651          info->rgAltEntry[0].dwAltNameChoice);
1652         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1653          "Unexpected DNS name\n");
1654         LocalFree(buf);
1655     }
1656     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1657      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1658     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1659     if (buf)
1660     {
1661         info = (CERT_ALT_NAME_INFO *)buf;
1662
1663         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1664          info->cAltEntry);
1665         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1666          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1667          info->rgAltEntry[0].dwAltNameChoice);
1668         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1669          "Unexpected IP address length %d\n",
1670           U(info->rgAltEntry[0]).IPAddress.cbData);
1671         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1672          sizeof(localhost)), "Unexpected IP address value\n");
1673         LocalFree(buf);
1674     }
1675     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1676      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1677     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1678     if (buf)
1679     {
1680         info = (CERT_ALT_NAME_INFO *)buf;
1681
1682         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1683          info->cAltEntry);
1684         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1685          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1686          info->rgAltEntry[0].dwAltNameChoice);
1687         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1688            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1689         LocalFree(buf);
1690     }
1691     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1692      encodedDirectoryName, sizeof(encodedDirectoryName),
1693      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1694     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1695     if (buf)
1696     {
1697         info = (CERT_ALT_NAME_INFO *)buf;
1698
1699         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1700          info->cAltEntry);
1701         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1702          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1703          info->rgAltEntry[0].dwAltNameChoice);
1704         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1705          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1706           U(info->rgAltEntry[0]).DirectoryName.cbData);
1707         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1708          encodedCommonName, sizeof(encodedCommonName)),
1709          "Unexpected directory name value\n");
1710         LocalFree(buf);
1711     }
1712     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1713      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1714      NULL, &buf, &bufSize);
1715     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1716      * particular failure, just that it doesn't decode.
1717      * It succeeds on (broken) Windows versions that haven't addressed
1718      * embedded NULLs in alternate names.
1719      */
1720     ok(!ret || broken(ret), "expected failure\n");
1721     /* An embedded bell character is allowed, however. */
1722     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1723      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1724      NULL, &buf, &bufSize);
1725     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1726     if (ret)
1727     {
1728         info = (CERT_ALT_NAME_INFO *)buf;
1729
1730         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1731          info->cAltEntry);
1732         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1733          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1734          info->rgAltEntry[0].dwAltNameChoice);
1735         LocalFree(buf);
1736     }
1737     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1738      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1739      NULL, &buf, &bufSize);
1740     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1741      * about the particular failure, just that it doesn't decode.
1742      * It succeeds on (broken) Windows versions that haven't addressed
1743      * embedded NULLs in alternate names.
1744      */
1745     ok(!ret || broken(ret), "expected failure\n");
1746 }
1747
1748 struct UnicodeExpectedError
1749 {
1750     DWORD   valueType;
1751     LPCWSTR str;
1752     DWORD   errorIndex;
1753     DWORD   error;
1754 };
1755
1756 static const WCHAR oneW[] = { '1',0 };
1757 static const WCHAR aW[] = { 'a',0 };
1758 static const WCHAR quoteW[] = { '"', 0 };
1759
1760 static struct UnicodeExpectedError unicodeErrors[] = {
1761  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1762  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1763  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1764  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1765  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1766  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1767 };
1768
1769 struct UnicodeExpectedResult
1770 {
1771     DWORD           valueType;
1772     LPCWSTR         str;
1773     CRYPT_DATA_BLOB encoded;
1774 };
1775
1776 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1777 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1778 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1779 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1780 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1781 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1782 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1783 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1784 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1785 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1786 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1787 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1788  0x5b };
1789 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1790  0x6f,0x5b };
1791 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1792  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1793 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1794  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1795
1796 static struct UnicodeExpectedResult unicodeResults[] = {
1797  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1798  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1799  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1800  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1801  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1802  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1803  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1804  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1805  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1806  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1807  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1808  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1809  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1810 };
1811
1812 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1813  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1814  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1815 };
1816
1817 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1818 {
1819     BYTE *buf = NULL;
1820     DWORD size = 0, i;
1821     BOOL ret;
1822     CERT_NAME_VALUE value;
1823
1824     if (0)
1825     {
1826         /* Crashes on win9x */
1827         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1828          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1829         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1830          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1831     }
1832     /* Have to have a string of some sort */
1833     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1834     value.Value.pbData = NULL;
1835     value.Value.cbData = 0;
1836     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1837      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1838     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1839      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1840     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1841     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1842      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1843     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1844      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1845     value.dwValueType = CERT_RDN_ANY_TYPE;
1846     value.Value.pbData = (LPBYTE)oneW;
1847     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1848      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1849     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1850      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1851     value.Value.cbData = sizeof(oneW);
1852     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1853      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1854     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1855      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1856     /* An encoded string with specified length isn't good enough either */
1857     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1858     value.Value.pbData = oneUniversal;
1859     value.Value.cbData = sizeof(oneUniversal);
1860     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1861      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1862     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1863      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1864     /* More failure checking */
1865     value.Value.cbData = 0;
1866     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1867     {
1868         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1869         value.dwValueType = unicodeErrors[i].valueType;
1870         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1871          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1872         ok(!ret && GetLastError() == unicodeErrors[i].error,
1873          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1874          unicodeErrors[i].error, GetLastError());
1875         ok(size == unicodeErrors[i].errorIndex,
1876          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1877          size);
1878     }
1879     /* cbData can be zero if the string is NULL-terminated */
1880     value.Value.cbData = 0;
1881     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1882     {
1883         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1884         value.dwValueType = unicodeResults[i].valueType;
1885         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1886          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1887         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1888          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1889         if (buf)
1890         {
1891             ok(size == unicodeResults[i].encoded.cbData,
1892              "Value type %d: expected size %d, got %d\n",
1893              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1894             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1895              "Value type %d: unexpected value\n", value.dwValueType);
1896             LocalFree(buf);
1897         }
1898     }
1899     /* These "encode," but they do so by truncating each unicode character
1900      * rather than properly encoding it.  Kept separate from the proper results,
1901      * because the encoded forms won't decode to their original strings.
1902      */
1903     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1904     {
1905         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1906         value.dwValueType = unicodeWeirdness[i].valueType;
1907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1908          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1909         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1910         if (buf)
1911         {
1912             ok(size == unicodeWeirdness[i].encoded.cbData,
1913              "Value type %d: expected size %d, got %d\n",
1914              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1915             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1916              "Value type %d: unexpected value\n", value.dwValueType);
1917             LocalFree(buf);
1918         }
1919     }
1920 }
1921
1922 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1923 {
1924     if (n <= 0) return 0;
1925     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1926     return *str1 - *str2;
1927 }
1928
1929 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1930 {
1931     DWORD i;
1932
1933     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1934     {
1935         BYTE *buf = NULL;
1936         BOOL ret;
1937         DWORD size = 0;
1938
1939         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1940          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1941          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1942         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1943          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1944         if (ret && buf)
1945         {
1946             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1947
1948             ok(value->dwValueType == unicodeResults[i].valueType,
1949              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1950              value->dwValueType);
1951             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1952              value->Value.cbData / sizeof(WCHAR)),
1953              "Unexpected decoded value for index %d (value type %d)\n", i,
1954              unicodeResults[i].valueType);
1955             LocalFree(buf);
1956         }
1957     }
1958 }
1959
1960 struct encodedOctets
1961 {
1962     const BYTE *val;
1963     const BYTE *encoded;
1964 };
1965
1966 static const unsigned char bin46[] = { 'h','i',0 };
1967 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1968 static const unsigned char bin48[] = {
1969      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1970 static const unsigned char bin49[] = {
1971      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1972 static const unsigned char bin50[] = { 0 };
1973 static const unsigned char bin51[] = { 0x04,0x00,0 };
1974
1975 static const struct encodedOctets octets[] = {
1976     { bin46, bin47 },
1977     { bin48, bin49 },
1978     { bin50, bin51 },
1979 };
1980
1981 static void test_encodeOctets(DWORD dwEncoding)
1982 {
1983     CRYPT_DATA_BLOB blob;
1984     DWORD i;
1985
1986     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1987     {
1988         BYTE *buf = NULL;
1989         BOOL ret;
1990         DWORD bufSize = 0;
1991
1992         blob.cbData = strlen((const char*)octets[i].val);
1993         blob.pbData = (BYTE*)octets[i].val;
1994         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1995          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1996         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1997         if (buf)
1998         {
1999             ok(buf[0] == 4,
2000              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2001             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2002              buf[1], octets[i].encoded[1]);
2003             ok(!memcmp(buf + 1, octets[i].encoded + 1,
2004              octets[i].encoded[1] + 1), "Got unexpected value\n");
2005             LocalFree(buf);
2006         }
2007     }
2008 }
2009
2010 static void test_decodeOctets(DWORD dwEncoding)
2011 {
2012     DWORD i;
2013
2014     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2015     {
2016         BYTE *buf = NULL;
2017         BOOL ret;
2018         DWORD bufSize = 0;
2019
2020         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2021          octets[i].encoded, octets[i].encoded[1] + 2,
2022          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2023         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2024         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2025          "Expected size >= %d, got %d\n",
2026            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2027         ok(buf != NULL, "Expected allocated buffer\n");
2028         if (buf)
2029         {
2030             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2031
2032             if (blob->cbData)
2033                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2034                  "Unexpected value\n");
2035             LocalFree(buf);
2036         }
2037     }
2038 }
2039
2040 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2041
2042 struct encodedBits
2043 {
2044     DWORD cUnusedBits;
2045     const BYTE *encoded;
2046     DWORD cbDecoded;
2047     const BYTE *decoded;
2048 };
2049
2050 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2051 static const unsigned char bin53[] = { 0xff,0xff };
2052 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2053 static const unsigned char bin55[] = { 0xff,0xfe };
2054 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2055 static const unsigned char bin57[] = { 0xfe };
2056 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2057
2058 static const struct encodedBits bits[] = {
2059     /* normal test cases */
2060     { 0, bin52, 2, bin53 },
2061     { 1, bin54, 2, bin55 },
2062     /* strange test case, showing cUnusedBits >= 8 is allowed */
2063     { 9, bin56, 1, bin57 },
2064 };
2065
2066 static void test_encodeBits(DWORD dwEncoding)
2067 {
2068     DWORD i;
2069
2070     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2071     {
2072         CRYPT_BIT_BLOB blob;
2073         BOOL ret;
2074         BYTE *buf = NULL;
2075         DWORD bufSize = 0;
2076
2077         blob.cbData = sizeof(bytesToEncode);
2078         blob.pbData = (BYTE *)bytesToEncode;
2079         blob.cUnusedBits = bits[i].cUnusedBits;
2080         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2081          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2082         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2083         if (buf)
2084         {
2085             ok(bufSize == bits[i].encoded[1] + 2,
2086              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2087              bits[i].encoded[1] + 2);
2088             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2089              "%d: Unexpected value\n", i);
2090             LocalFree(buf);
2091         }
2092     }
2093 }
2094
2095 static void test_decodeBits(DWORD dwEncoding)
2096 {
2097     static const BYTE ber[] = "\x03\x02\x01\xff";
2098     static const BYTE berDecoded = 0xfe;
2099     DWORD i;
2100     BOOL ret;
2101     BYTE *buf = NULL;
2102     DWORD bufSize = 0;
2103
2104     /* normal cases */
2105     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2106     {
2107         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2108          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2109          &bufSize);
2110         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2111         if (buf)
2112         {
2113             CRYPT_BIT_BLOB *blob;
2114
2115             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2116                "Got unexpected size %d\n", bufSize);
2117             blob = (CRYPT_BIT_BLOB *)buf;
2118             ok(blob->cbData == bits[i].cbDecoded,
2119              "Got unexpected length %d, expected %d\n", blob->cbData,
2120              bits[i].cbDecoded);
2121             if (blob->cbData && bits[i].cbDecoded)
2122                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2123                  "Unexpected value\n");
2124             LocalFree(buf);
2125         }
2126     }
2127     /* special case: check that something that's valid in BER but not in DER
2128      * decodes successfully
2129      */
2130     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2131      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2132     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2133     if (buf)
2134     {
2135         CRYPT_BIT_BLOB *blob;
2136
2137         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2138            "Got unexpected size %d\n", bufSize);
2139         blob = (CRYPT_BIT_BLOB *)buf;
2140         ok(blob->cbData == sizeof(berDecoded),
2141            "Got unexpected length %d\n", blob->cbData);
2142         if (blob->cbData)
2143             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2144         LocalFree(buf);
2145     }
2146 }
2147
2148 struct Constraints2
2149 {
2150     CERT_BASIC_CONSTRAINTS2_INFO info;
2151     const BYTE *encoded;
2152 };
2153
2154 static const unsigned char bin59[] = { 0x30,0x00 };
2155 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2156 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2157 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2158 static const struct Constraints2 constraints2[] = {
2159  /* empty constraints */
2160  { { FALSE, FALSE, 0}, bin59 },
2161  /* can be a CA */
2162  { { TRUE,  FALSE, 0}, bin60 },
2163  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2164   * but that's not the case
2165   */
2166  { { FALSE, TRUE,  0}, bin61 },
2167  /* can be a CA and has path length constraints set */
2168  { { TRUE,  TRUE,  1}, bin62 },
2169 };
2170
2171 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2172 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2173  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2174  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2175  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2176 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2177  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2178  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2179  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2180  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2181
2182 static void test_encodeBasicConstraints(DWORD dwEncoding)
2183 {
2184     DWORD i, bufSize = 0;
2185     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2186     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2187      (LPBYTE)encodedDomainName };
2188     BOOL ret;
2189     BYTE *buf = NULL;
2190
2191     /* First test with the simpler info2 */
2192     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2193     {
2194         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2195          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2196          &bufSize);
2197         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2198         if (buf)
2199         {
2200             ok(bufSize == constraints2[i].encoded[1] + 2,
2201              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2202              bufSize);
2203             ok(!memcmp(buf, constraints2[i].encoded,
2204              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2205             LocalFree(buf);
2206         }
2207     }
2208     /* Now test with more complex basic constraints */
2209     info.SubjectType.cbData = 0;
2210     info.fPathLenConstraint = FALSE;
2211     info.cSubtreesConstraint = 0;
2212     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2213      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2214     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2215      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2216     if (buf)
2217     {
2218         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2219         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2220          "Unexpected value\n");
2221         LocalFree(buf);
2222     }
2223     /* None of the certs I examined had any subtree constraint, but I test one
2224      * anyway just in case.
2225      */
2226     info.cSubtreesConstraint = 1;
2227     info.rgSubtreesConstraint = &nameBlob;
2228     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2229      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2230     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2231      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2232     if (buf)
2233     {
2234         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2235         ok(!memcmp(buf, constraintWithDomainName,
2236          sizeof(constraintWithDomainName)), "Unexpected value\n");
2237         LocalFree(buf);
2238     }
2239     /* FIXME: test encoding with subject type. */
2240 }
2241
2242 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2243
2244 static void test_decodeBasicConstraints(DWORD dwEncoding)
2245 {
2246     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2247      0xff };
2248     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2249     DWORD i;
2250     BOOL ret;
2251     BYTE *buf = NULL;
2252     DWORD bufSize = 0;
2253
2254     /* First test with simpler info2 */
2255     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2256     {
2257         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2258          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2259          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2260         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2261          GetLastError());
2262         if (buf)
2263         {
2264             CERT_BASIC_CONSTRAINTS2_INFO *info =
2265              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2266
2267             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2268              "Unexpected value for item %d\n", i);
2269             LocalFree(buf);
2270         }
2271     }
2272     /* Check with the order of encoded elements inverted */
2273     buf = (PBYTE)1;
2274     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2275      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2276      &bufSize);
2277     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2278      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2279      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2280      GetLastError());
2281     ok(!buf, "Expected buf to be set to NULL\n");
2282     /* Check with a non-DER bool */
2283     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2284      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2285      &buf, &bufSize);
2286     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2287     if (buf)
2288     {
2289         CERT_BASIC_CONSTRAINTS2_INFO *info =
2290          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2291
2292         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2293         LocalFree(buf);
2294     }
2295     /* Check with a non-basic constraints value */
2296     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2297      encodedCommonName, encodedCommonName[1] + 2,
2298      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2299     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2300      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2301      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2302      GetLastError());
2303     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2304     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2305      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2306      &buf, &bufSize);
2307     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2308     if (buf)
2309     {
2310         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2311
2312         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2313         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2314         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2315         LocalFree(buf);
2316     }
2317     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2318      constraintWithDomainName, sizeof(constraintWithDomainName),
2319      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2320     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2321     if (buf)
2322     {
2323         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2324
2325         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2326         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2327         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2328         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2329         {
2330             ok(info->rgSubtreesConstraint[0].cbData ==
2331              sizeof(encodedDomainName), "Wrong size %d\n",
2332              info->rgSubtreesConstraint[0].cbData);
2333             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2334              sizeof(encodedDomainName)), "Unexpected value\n");
2335         }
2336         LocalFree(buf);
2337     }
2338 }
2339
2340 /* These are terrible public keys of course, I'm just testing encoding */
2341 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2342 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2343 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2344 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2345 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2346 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2347 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2349
2350 struct EncodedRSAPubKey
2351 {
2352     const BYTE *modulus;
2353     size_t modulusLen;
2354     const BYTE *encoded;
2355     size_t decodedModulusLen;
2356 };
2357
2358 struct EncodedRSAPubKey rsaPubKeys[] = {
2359     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2360     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2361     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2362     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2363 };
2364
2365 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2366 {
2367     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2368     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2369     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2370     BOOL ret;
2371     BYTE *buf = NULL;
2372     DWORD bufSize = 0, i;
2373
2374     /* Try with a bogus blob type */
2375     hdr->bType = 2;
2376     hdr->bVersion = CUR_BLOB_VERSION;
2377     hdr->reserved = 0;
2378     hdr->aiKeyAlg = CALG_RSA_KEYX;
2379     rsaPubKey->magic = 0x31415352;
2380     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2381     rsaPubKey->pubexp = 65537;
2382     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2383      sizeof(modulus1));
2384
2385     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2386      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2387     ok(!ret && GetLastError() == E_INVALIDARG,
2388      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2389     /* Now with a bogus reserved field */
2390     hdr->bType = PUBLICKEYBLOB;
2391     hdr->reserved = 1;
2392     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2393      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2394     if (buf)
2395     {
2396         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2397          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2398         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2399         LocalFree(buf);
2400     }
2401     /* Now with a bogus blob version */
2402     hdr->reserved = 0;
2403     hdr->bVersion = 0;
2404     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2405      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2406     if (buf)
2407     {
2408         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2409          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2410         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2411         LocalFree(buf);
2412     }
2413     /* And with a bogus alg ID */
2414     hdr->bVersion = CUR_BLOB_VERSION;
2415     hdr->aiKeyAlg = CALG_DES;
2416     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2417      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2418     if (buf)
2419     {
2420         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2421          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2422         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2423         LocalFree(buf);
2424     }
2425     /* Check a couple of RSA-related OIDs */
2426     hdr->aiKeyAlg = CALG_RSA_KEYX;
2427     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2428      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2429     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2430      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2431     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2432      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2433     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2434      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2435     /* Finally, all valid */
2436     hdr->aiKeyAlg = CALG_RSA_KEYX;
2437     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2438     {
2439         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2440          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2441         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2442          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2443         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2444         if (buf)
2445         {
2446             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2447              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2448              bufSize);
2449             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2450              "Unexpected value\n");
2451             LocalFree(buf);
2452         }
2453     }
2454 }
2455
2456 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2457 {
2458     DWORD i;
2459     LPBYTE buf = NULL;
2460     DWORD bufSize = 0;
2461     BOOL ret;
2462
2463     /* Try with a bad length */
2464     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2465      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2466      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2467     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2468      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2469      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2470      GetLastError());
2471     /* Try with a couple of RSA-related OIDs */
2472     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2473      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2474      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2475     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2476      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2477     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2478      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2479      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2480     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2481      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2482     /* Now try success cases */
2483     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2484     {
2485         bufSize = 0;
2486         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2487          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2488          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2489         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2490         if (buf)
2491         {
2492             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2493             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2494
2495             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2496              rsaPubKeys[i].decodedModulusLen,
2497              "Wrong size %d\n", bufSize);
2498             ok(hdr->bType == PUBLICKEYBLOB,
2499              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2500              hdr->bType);
2501             ok(hdr->bVersion == CUR_BLOB_VERSION,
2502              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2503              CUR_BLOB_VERSION, hdr->bVersion);
2504             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2505              hdr->reserved);
2506             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2507              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2508             ok(rsaPubKey->magic == 0x31415352,
2509              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2510             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2511              "Wrong bit len %d\n", rsaPubKey->bitlen);
2512             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2513              rsaPubKey->pubexp);
2514             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2515              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2516              "Unexpected modulus\n");
2517             LocalFree(buf);
2518         }
2519     }
2520 }
2521
2522 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2523  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2524  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2525
2526 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2527  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2528  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2529  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2530
2531 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2532 {
2533     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2534     CRYPT_SEQUENCE_OF_ANY seq;
2535     DWORD i;
2536     BOOL ret;
2537     BYTE *buf = NULL;
2538     DWORD bufSize = 0;
2539
2540     /* Encode a homogeneous sequence */
2541     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2542     {
2543         blobs[i].cbData = ints[i].encoded[1] + 2;
2544         blobs[i].pbData = (BYTE *)ints[i].encoded;
2545     }
2546     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2547     seq.rgValue = blobs;
2548
2549     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2550      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2551     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2552     if (buf)
2553     {
2554         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2555         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2556         LocalFree(buf);
2557     }
2558     /* Change the type of the first element in the sequence, and give it
2559      * another go
2560      */
2561     blobs[0].cbData = times[0].encodedTime[1] + 2;
2562     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2563     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2564      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2565     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2566     if (buf)
2567     {
2568         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2569         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2570          "Unexpected value\n");
2571         LocalFree(buf);
2572     }
2573 }
2574
2575 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2576 {
2577     BOOL ret;
2578     BYTE *buf = NULL;
2579     DWORD bufSize = 0;
2580
2581     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2582      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2583     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2584     if (buf)
2585     {
2586         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2587         DWORD i;
2588
2589         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2590          "Wrong elements %d\n", seq->cValue);
2591         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2592         {
2593             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2594              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2595              seq->rgValue[i].cbData);
2596             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2597              ints[i].encoded[1] + 2), "Unexpected value\n");
2598         }
2599         LocalFree(buf);
2600     }
2601     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2602      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2603      &bufSize);
2604     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2605     if (buf)
2606     {
2607         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2608
2609         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2610          "Wrong elements %d\n", seq->cValue);
2611         /* Just check the first element since it's all that changed */
2612         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2613          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2614          seq->rgValue[0].cbData);
2615         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2616          times[0].encodedTime[1] + 2), "Unexpected value\n");
2617         LocalFree(buf);
2618     }
2619 }
2620
2621 struct encodedExtensions
2622 {
2623     CERT_EXTENSIONS exts;
2624     const BYTE *encoded;
2625 };
2626
2627 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2628 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2629 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2630 static CERT_EXTENSION criticalExt =
2631  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2632 static CERT_EXTENSION nonCriticalExt =
2633  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2634 static CHAR oid_short[] = "1.1";
2635 static CERT_EXTENSION extWithShortOid =
2636  { oid_short, FALSE, { 0, NULL } };
2637
2638 static const BYTE ext0[] = { 0x30,0x00 };
2639 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2640                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2641 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2642                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2643 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2644
2645 static const struct encodedExtensions exts[] = {
2646  { { 0, NULL }, ext0 },
2647  { { 1, &criticalExt }, ext1 },
2648  { { 1, &nonCriticalExt }, ext2 },
2649  { { 1, &extWithShortOid }, ext3 }
2650 };
2651
2652 static void test_encodeExtensions(DWORD dwEncoding)
2653 {
2654     DWORD i;
2655
2656     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2657     {
2658         BOOL ret;
2659         BYTE *buf = NULL;
2660         DWORD bufSize = 0;
2661
2662         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2663          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2664         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2665         if (buf)
2666         {
2667             ok(bufSize == exts[i].encoded[1] + 2,
2668              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2669             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2670              "Unexpected value\n");
2671             LocalFree(buf);
2672         }
2673     }
2674 }
2675
2676 static void test_decodeExtensions(DWORD dwEncoding)
2677 {
2678     DWORD i;
2679
2680     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2681     {
2682         BOOL ret;
2683         BYTE *buf = NULL;
2684         DWORD bufSize = 0;
2685
2686         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2687          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2688          NULL, &buf, &bufSize);
2689         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2690         if (buf)
2691         {
2692             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2693             DWORD j;
2694
2695             ok(ext->cExtension == exts[i].exts.cExtension,
2696              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2697              ext->cExtension);
2698             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2699             {
2700                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2701                  exts[i].exts.rgExtension[j].pszObjId),
2702                  "Expected OID %s, got %s\n",
2703                  exts[i].exts.rgExtension[j].pszObjId,
2704                  ext->rgExtension[j].pszObjId);
2705                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2706                  exts[i].exts.rgExtension[j].Value.pbData,
2707                  exts[i].exts.rgExtension[j].Value.cbData),
2708                  "Unexpected value\n");
2709             }
2710             LocalFree(buf);
2711         }
2712     }
2713 }
2714
2715 /* MS encodes public key info with a NULL if the algorithm identifier's
2716  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2717  * it encodes them by omitting the algorithm parameters.  It accepts either
2718  * form for decoding.
2719  */
2720 struct encodedPublicKey
2721 {
2722     CERT_PUBLIC_KEY_INFO info;
2723     const BYTE *encoded;
2724     const BYTE *encodedNoNull;
2725     CERT_PUBLIC_KEY_INFO decoded;
2726 };
2727
2728 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2729  0xe, 0xf };
2730 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2731
2732 static const unsigned char bin64[] = {
2733     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2734 static const unsigned char bin65[] = {
2735     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2736 static const unsigned char bin66[] = {
2737     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2738 static const unsigned char bin67[] = {
2739     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2740 static const unsigned char bin68[] = {
2741     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2742     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2743 static const unsigned char bin69[] = {
2744     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2745     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2746 static const unsigned char bin70[] = {
2747     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2748     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2749     0x0f};
2750 static const unsigned char bin71[] = {
2751     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2752     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2753     0x0f};
2754 static unsigned char bin72[] = { 0x05,0x00};
2755
2756 static CHAR oid_bogus[] = "1.2.3",
2757             oid_rsa[]   = szOID_RSA;
2758
2759 static const struct encodedPublicKey pubKeys[] = {
2760  /* with a bogus OID */
2761  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2762   bin64, bin65,
2763   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2764  /* some normal keys */
2765  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2766   bin66, bin67,
2767   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2768  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2769   bin68, bin69,
2770   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2771  /* with add'l parameters--note they must be DER-encoded */
2772  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2773   (BYTE *)aKey, 0 } },
2774   bin70, bin71,
2775   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2776   (BYTE *)aKey, 0 } } },
2777 };
2778
2779 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2780 {
2781     DWORD i;
2782
2783     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2784     {
2785         BOOL ret;
2786         BYTE *buf = NULL;
2787         DWORD bufSize = 0;
2788
2789         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2790          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2791          &bufSize);
2792         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2793          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2794         if (buf)
2795         {
2796             ok(bufSize == pubKeys[i].encoded[1] + 2,
2797              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2798             if (bufSize == pubKeys[i].encoded[1] + 2)
2799                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2800                  "Unexpected value\n");
2801             LocalFree(buf);
2802         }
2803     }
2804 }
2805
2806 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2807  const CERT_PUBLIC_KEY_INFO *got)
2808 {
2809     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2810      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2811      got->Algorithm.pszObjId);
2812     ok(expected->Algorithm.Parameters.cbData ==
2813      got->Algorithm.Parameters.cbData,
2814      "Expected parameters of %d bytes, got %d\n",
2815      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2816     if (expected->Algorithm.Parameters.cbData)
2817         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2818          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2819          "Unexpected algorithm parameters\n");
2820     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2821      "Expected public key of %d bytes, got %d\n",
2822      expected->PublicKey.cbData, got->PublicKey.cbData);
2823     if (expected->PublicKey.cbData)
2824         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2825          got->PublicKey.cbData), "Unexpected public key value\n");
2826 }
2827
2828 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2829 {
2830     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2831      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2832      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2833      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2834     DWORD i;
2835     BOOL ret;
2836     BYTE *buf = NULL;
2837     DWORD bufSize = 0;
2838
2839     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2840     {
2841         /* The NULL form decodes to the decoded member */
2842         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2843          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2844          NULL, &buf, &bufSize);
2845         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2846         if (buf)
2847         {
2848             comparePublicKeyInfo(&pubKeys[i].decoded,
2849              (CERT_PUBLIC_KEY_INFO *)buf);
2850             LocalFree(buf);
2851         }
2852         /* The non-NULL form decodes to the original */
2853         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2854          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2855          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2856         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2857         if (buf)
2858         {
2859             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2860             LocalFree(buf);
2861         }
2862     }
2863     /* Test with bogus (not valid DER) parameters */
2864     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2865      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2866      NULL, &buf, &bufSize);
2867     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2868      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2869      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2870      GetLastError());
2871 }
2872
2873 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2874  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2875  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2876  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2877  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2878 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2879  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2880  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2881  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2882  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2883 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2884  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2885  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2886  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2887  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2888 static const BYTE v4Cert[] = {
2889 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2890 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2891 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2892 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2893 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2894  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2895  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2896  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2897  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2898  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2899  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2900 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2901  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2902  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2903  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2904  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2905  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2906  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2907 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2908  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2909  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2910  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2911  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2912  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2913  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2914  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2915  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2916  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2917 static const BYTE v1CertWithPubKey[] = {
2918 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2919 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2920 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2921 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2922 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2923 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2924 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2925 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2926 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2927 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2928 0x01,0x01 };
2929 static const BYTE v1CertWithPubKeyNoNull[] = {
2930 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2931 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2932 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2933 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2934 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2935 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2936 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2937 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2938 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2939 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2940 static const BYTE v1CertWithSubjectKeyId[] = {
2941 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2942 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2943 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2944 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2945 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2946 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2947 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2948 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2949 0x4c,0x61,0x6e,0x67,0x00 };
2950 static const BYTE v1CertWithIssuerUniqueId[] = {
2951 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2952 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2953 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2954 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2955 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2956 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2957 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2958 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2959 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2960 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2961 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2962 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2963 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2964 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2965 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2966 0x01,0x01,0xff,0x02,0x01,0x01 };
2967 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2968 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2969 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2970 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2971 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2972 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2973 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2974 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2975 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2976 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2977 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2978 0xff,0x02,0x01,0x01 };
2979
2980 static const BYTE serialNum[] = { 0x01 };
2981
2982 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2983 {
2984     BOOL ret;
2985     BYTE *buf = NULL;
2986     DWORD size = 0;
2987     CERT_INFO info = { 0 };
2988     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2989     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2990     CERT_EXTENSION ext;
2991
2992     if (0)
2993     {
2994         /* Test with NULL pvStructInfo (crashes on win9x) */
2995         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2996          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2997         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2998          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2999     }
3000     /* Test with a V1 cert */
3001     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3002      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3003     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3004      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3005     if (buf)
3006     {
3007         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3008          v1Cert[1] + 2, size);
3009         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3010         LocalFree(buf);
3011     }
3012     /* Test v2 cert */
3013     info.dwVersion = CERT_V2;
3014     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3015      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3016     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3017      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3018     if (buf)
3019     {
3020         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3021         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3022         LocalFree(buf);
3023     }
3024     /* Test v3 cert */
3025     info.dwVersion = CERT_V3;
3026     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3027      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3028     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3029      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3030     if (buf)
3031     {
3032         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3033         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3034         LocalFree(buf);
3035     }
3036     /* A v4 cert? */
3037     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3038     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3039      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3040     if (buf)
3041     {
3042         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3043         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3044         LocalFree(buf);
3045     }
3046     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3047      * API doesn't prevent it)
3048      */
3049     info.dwVersion = CERT_V1;
3050     info.cExtension = 1;
3051     info.rgExtension = &criticalExt;
3052     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3053      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3054     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3055      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3056     if (buf)
3057     {
3058         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3059         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3060         LocalFree(buf);
3061     }
3062     /* test v1 cert with a serial number */
3063     info.SerialNumber.cbData = sizeof(serialNum);
3064     info.SerialNumber.pbData = (BYTE *)serialNum;
3065     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3066      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3067     if (buf)
3068     {
3069         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3070         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3071         LocalFree(buf);
3072     }
3073     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3074     info.dwVersion = CERT_V1;
3075     info.cExtension = 0;
3076     info.IssuerUniqueId.cbData = sizeof(serialNum);
3077     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3078     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3079      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3080     ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3081      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3082     if (buf)
3083     {
3084         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3085         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3086          "Got unexpected value\n");
3087         LocalFree(buf);
3088     }
3089     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3090     info.IssuerUniqueId.cbData = 0;
3091     info.IssuerUniqueId.pbData = NULL;
3092     info.cExtension = 1;
3093     info.rgExtension = &criticalExt;
3094     info.Issuer.cbData = sizeof(encodedCommonName);
3095     info.Issuer.pbData = (BYTE *)encodedCommonName;
3096     info.Subject.cbData = sizeof(encodedCommonName);
3097     info.Subject.pbData = (BYTE *)encodedCommonName;
3098     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3099      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3100     if (buf)
3101     {
3102         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3103         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3104         LocalFree(buf);
3105     }
3106     /* Add a public key */
3107     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3108     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3109     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3110     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3111      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3112     if (buf)
3113     {
3114         ok(size == sizeof(v1CertWithPubKey) ||
3115          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3116         if (size == sizeof(v1CertWithPubKey))
3117             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3118         else if (size == sizeof(v1CertWithPubKeyNoNull))
3119             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3120              "Got unexpected value\n");
3121         LocalFree(buf);
3122     }
3123     /* Again add an issuer unique id */
3124     info.IssuerUniqueId.cbData = sizeof(serialNum);
3125     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3126     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3127      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3128     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3129     if (buf)
3130     {
3131         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3132          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3133          "Wrong size %d\n", size);
3134         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3135             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3136              size), "unexpected value\n");
3137         else if (size ==
3138          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3139             ok(!memcmp(buf,
3140              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3141              "unexpected value\n");
3142         LocalFree(buf);
3143     }
3144     /* Remove the public key, and add a subject key identifier extension */
3145     info.IssuerUniqueId.cbData = 0;
3146     info.IssuerUniqueId.pbData = NULL;
3147     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3148     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3149     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3150     ext.pszObjId = oid_subject_key_identifier;
3151     ext.fCritical = FALSE;
3152     ext.Value.cbData = sizeof(octetCommonNameValue);
3153     ext.Value.pbData = octetCommonNameValue;
3154     info.cExtension = 1;
3155     info.rgExtension = &ext;
3156     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3157      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3158     if (buf)
3159     {
3160         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3161         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3162         LocalFree(buf);
3163     }
3164 }
3165
3166 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3167 {
3168     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3169      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3170     BOOL ret;
3171     BYTE *buf = NULL;
3172     DWORD size = 0, i;
3173
3174     /* Test with NULL pbEncoded */
3175     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3176      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3177     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3178      GetLastError() == OSS_BAD_ARG /* Win9x */),
3179      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3180     if (0)
3181     {
3182         /* Crashes on win9x */
3183         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3184          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3185         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3186          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3187     }
3188     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3189      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3190      * serial number, an issuer, a subject, and a public key.
3191      */
3192     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3193     {
3194         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3195          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3196          &buf, &size);
3197         ok(!ret, "Expected failure\n");
3198     }
3199     /* The following succeeds, even though v1 certs are not allowed to have
3200      * extensions.
3201      */
3202     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3203      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3204      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3205     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3206     if (ret)
3207     {
3208         CERT_INFO *info = (CERT_INFO *)buf;
3209
3210         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3211         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3212          info->dwVersion);
3213         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3214          info->cExtension);
3215         LocalFree(buf);
3216     }
3217     /* The following also succeeds, even though V1 certs are not allowed to
3218      * have issuer unique ids.
3219      */
3220     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3221      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3222      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3223      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3224     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3225     if (ret)
3226     {
3227         CERT_INFO *info = (CERT_INFO *)buf;
3228
3229         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3230         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3231          info->dwVersion);
3232         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3233          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3234         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3235          "unexpected issuer unique id value\n");
3236         LocalFree(buf);
3237     }
3238     /* Now check with serial number, subject and issuer specified */
3239     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3240      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3241     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3242     if (buf)
3243     {
3244         CERT_INFO *info = (CERT_INFO *)buf;
3245
3246         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3247         ok(info->SerialNumber.cbData == 1,
3248          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3249         ok(*info->SerialNumber.pbData == *serialNum,
3250          "Expected serial number %d, got %d\n", *serialNum,
3251          *info->SerialNumber.pbData);
3252         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3253          "Wrong size %d\n", info->Issuer.cbData);
3254         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3255          "Unexpected issuer\n");
3256         ok(info->Subject.cbData == sizeof(encodedCommonName),
3257          "Wrong size %d\n", info->Subject.cbData);
3258         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3259          info->Subject.cbData), "Unexpected subject\n");
3260         LocalFree(buf);
3261     }
3262     /* Check again with pub key specified */
3263     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3264      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3265      &buf, &size);
3266     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3267     if (buf)
3268     {
3269         CERT_INFO *info = (CERT_INFO *)buf;
3270
3271         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3272         ok(info->SerialNumber.cbData == 1,
3273          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3274         ok(*info->SerialNumber.pbData == *serialNum,
3275          "Expected serial number %d, got %d\n", *serialNum,
3276          *info->SerialNumber.pbData);
3277         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3278          "Wrong size %d\n", info->Issuer.cbData);
3279         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3280          "Unexpected issuer\n");
3281         ok(info->Subject.cbData == sizeof(encodedCommonName),
3282          "Wrong size %d\n", info->Subject.cbData);
3283         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3284          info->Subject.cbData), "Unexpected subject\n");
3285         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3286          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3287          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3288         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3289          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3290         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3291          sizeof(aKey)), "Unexpected public key\n");
3292         LocalFree(buf);
3293     }
3294 }
3295
3296 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3297  0xe, 0xf };
3298
3299 static const BYTE signedBigCert[] = {
3300  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3301  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3302  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3303  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3304  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3305  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3306  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3307  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3308  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3309  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3310  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3311  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3312
3313 static void test_encodeCert(DWORD dwEncoding)
3314 {
3315     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3316      * also that bigCert is a NULL-terminated string, so don't count its
3317      * last byte (otherwise the signed cert won't decode.)
3318      */
3319     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3320      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3321     BOOL ret;
3322     BYTE *buf = NULL;
3323     DWORD bufSize = 0;
3324
3325     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3326      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3327     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3328     if (buf)
3329     {
3330         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3331         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3332         LocalFree(buf);
3333     }
3334 }
3335
3336 static void test_decodeCert(DWORD dwEncoding)
3337 {
3338     BOOL ret;
3339     BYTE *buf = NULL;
3340     DWORD size = 0;
3341
3342     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3343      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3344     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3345     if (buf)
3346     {
3347         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3348
3349         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3350          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3351         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3352          "Unexpected cert\n");
3353         ok(info->Signature.cbData == sizeof(hash),
3354          "Wrong signature size %d\n", info->Signature.cbData);
3355         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3356          "Unexpected signature\n");
3357         LocalFree(buf);
3358     }
3359     /* A signed cert decodes as a CERT_INFO too */
3360     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3361      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3362     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3363     if (buf)
3364     {
3365         CERT_INFO *info = (CERT_INFO *)buf;
3366
3367         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3368         ok(info->SerialNumber.cbData == 1,
3369          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3370         ok(*info->SerialNumber.pbData == *serialNum,
3371          "Expected serial number %d, got %d\n", *serialNum,
3372          *info->SerialNumber.pbData);
3373         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3374          "Wrong size %d\n", info->Issuer.cbData);
3375         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3376          "Unexpected issuer\n");
3377         ok(info->Subject.cbData == sizeof(encodedCommonName),
3378          "Wrong size %d\n", info->Subject.cbData);
3379         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3380          info->Subject.cbData), "Unexpected subject\n");
3381         LocalFree(buf);
3382     }
3383 }
3384
3385 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3386 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3387  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3388  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3389 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3390  0x00, 0x03 };
3391 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3392  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3393  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3394 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3395  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3396  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3397  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3398  0x2e, 0x6f, 0x72, 0x67 };
3399 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3400  CRL_REASON_AFFILIATION_CHANGED;
3401
3402 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3403 {
3404     CRL_DIST_POINTS_INFO info = { 0 };
3405     CRL_DIST_POINT point = { { 0 } };
3406     CERT_ALT_NAME_ENTRY entry = { 0 };
3407     BOOL ret;
3408     BYTE *buf = NULL;
3409     DWORD size = 0;
3410
3411     /* Test with an empty info */
3412     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3413      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3414     ok(!ret && GetLastError() == E_INVALIDARG,
3415      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3416     /* Test with one empty dist point */
3417     info.cDistPoint = 1;
3418     info.rgDistPoint = &point;
3419     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3420      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3421     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3422     if (buf)
3423     {
3424         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3425         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3426         LocalFree(buf);
3427     }
3428     /* A dist point with an invalid name */
3429     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3430     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3431     U(entry).pwszURL = (LPWSTR)nihongoURL;
3432     U(point.DistPointName).FullName.cAltEntry = 1;
3433     U(point.DistPointName).FullName.rgAltEntry = &entry;
3434     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3435      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3436     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3437      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3438     /* The first invalid character is at index 7 */
3439     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3440      "Expected invalid char at index 7, got %d\n",
3441      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3442     /* A dist point with (just) a valid name */
3443     U(entry).pwszURL = (LPWSTR)url;
3444     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3445      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3446     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3447     if (buf)
3448     {
3449         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3450         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3451         LocalFree(buf);
3452     }
3453     /* A dist point with (just) reason flags */
3454     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3455     point.ReasonFlags.cbData = sizeof(crlReason);
3456     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3457     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3458      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3459     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3460     if (buf)
3461     {
3462         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3463         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3464         LocalFree(buf);
3465     }
3466     /* A dist point with just an issuer */
3467     point.ReasonFlags.cbData = 0;
3468     point.CRLIssuer.cAltEntry = 1;
3469     point.CRLIssuer.rgAltEntry = &entry;
3470     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3471      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3472     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3473     if (buf)
3474     {
3475         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3476         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3477         LocalFree(buf);
3478     }
3479     /* A dist point with both a name and an issuer */
3480     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3481     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3482      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3483     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3484     if (buf)
3485     {
3486         ok(size == sizeof(distPointWithUrlAndIssuer),
3487          "Wrong size %d\n", size);
3488         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3489         LocalFree(buf);
3490     }
3491 }
3492
3493 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3494 {
3495     BOOL ret;
3496     BYTE *buf = NULL;
3497     DWORD size = 0;
3498     PCRL_DIST_POINTS_INFO info;
3499     PCRL_DIST_POINT point;
3500     PCERT_ALT_NAME_ENTRY entry;
3501
3502     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3503      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3504      &buf, &size);
3505     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3506     if (ret)
3507     {
3508         info = (PCRL_DIST_POINTS_INFO)buf;
3509         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3510          "Wrong size %d\n", size);
3511         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3512          info->cDistPoint);
3513         point = info->rgDistPoint;
3514         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3515          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3516          point->DistPointName.dwDistPointNameChoice);
3517         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3518         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3519         LocalFree(buf);
3520     }
3521     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3522      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3523      &buf, &size);
3524     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3525     if (ret)
3526     {
3527         info = (PCRL_DIST_POINTS_INFO)buf;
3528         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3529          "Wrong size %d\n", size);
3530         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3531          info->cDistPoint);
3532         point = info->rgDistPoint;
3533         ok(point->DistPointName.dwDistPointNameChoice ==
3534          CRL_DIST_POINT_FULL_NAME,
3535          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3536          point->DistPointName.dwDistPointNameChoice);
3537         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3538          "Expected 1 name entry, got %d\n",
3539          U(point->DistPointName).FullName.cAltEntry);
3540         entry = U(point->DistPointName).FullName.rgAltEntry;
3541         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3542          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3543         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3544         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3545         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3546         LocalFree(buf);
3547     }
3548     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3549      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3550      NULL, &buf, &size);
3551     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3552     if (ret)
3553     {
3554         info = (PCRL_DIST_POINTS_INFO)buf;
3555         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3556          "Wrong size %d\n", size);
3557         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3558          info->cDistPoint);
3559         point = info->rgDistPoint;
3560         ok(point->DistPointName.dwDistPointNameChoice ==
3561          CRL_DIST_POINT_NO_NAME,
3562          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3563          point->DistPointName.dwDistPointNameChoice);
3564         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3565          "Expected reason length\n");
3566         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3567          "Unexpected reason\n");
3568         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3569         LocalFree(buf);
3570     }
3571     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3572      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3573      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3574     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3575     if (ret)
3576     {
3577         info = (PCRL_DIST_POINTS_INFO)buf;
3578         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3579          "Wrong size %d\n", size);
3580         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3581          info->cDistPoint);
3582         point = info->rgDistPoint;
3583         ok(point->DistPointName.dwDistPointNameChoice ==
3584          CRL_DIST_POINT_FULL_NAME,
3585          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3586          point->DistPointName.dwDistPointNameChoice);
3587         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3588          "Expected 1 name entry, got %d\n",
3589          U(point->DistPointName).FullName.cAltEntry);
3590         entry = U(point->DistPointName).FullName.rgAltEntry;
3591         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3592          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3593         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3594         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3595         ok(point->CRLIssuer.cAltEntry == 1,
3596          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3597         entry = point->CRLIssuer.rgAltEntry;
3598         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3599          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3600         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3601         LocalFree(buf);
3602     }
3603 }
3604
3605 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3606 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3607 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3608  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3609  0x67 };
3610
3611 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3612 {
3613     BOOL ret;
3614     BYTE *buf = NULL;
3615     DWORD size = 0;
3616     CRL_ISSUING_DIST_POINT point = { { 0 } };
3617     CERT_ALT_NAME_ENTRY entry;
3618
3619     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3620      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3621     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3622     {
3623         skip("no X509_ISSUING_DIST_POINT encode support\n");
3624         return;
3625     }
3626     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3627      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3628     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3629      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3630     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3631     if (buf)
3632     {
3633         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3634         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3635         LocalFree(buf);
3636     }
3637     /* nonsensical flags */
3638     point.fOnlyContainsUserCerts = TRUE;
3639     point.fOnlyContainsCACerts = TRUE;
3640     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3641      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3642     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3643     if (buf)
3644     {
3645         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3646         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3647         LocalFree(buf);
3648     }
3649     /* unimplemented name type */
3650     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3651     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3652     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3653      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3654     ok(!ret && GetLastError() == E_INVALIDARG,
3655      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3656     /* empty name */
3657     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3658     U(point.DistPointName).FullName.cAltEntry = 0;
3659     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3660      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3661     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3662     if (buf)
3663     {
3664         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3665         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3666         LocalFree(buf);
3667     }
3668     /* name with URL entry */
3669     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3670     U(entry).pwszURL = (LPWSTR)url;
3671     U(point.DistPointName).FullName.cAltEntry = 1;
3672     U(point.DistPointName).FullName.rgAltEntry = &entry;
3673     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3674      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3675     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3676     if (buf)
3677     {
3678         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3679         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3680         LocalFree(buf);
3681     }
3682 }
3683
3684 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3685  const CERT_ALT_NAME_ENTRY *got)
3686 {
3687     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3688      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3689      got->dwAltNameChoice);
3690     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3691     {
3692         switch (got->dwAltNameChoice)
3693         {
3694         case CERT_ALT_NAME_RFC822_NAME:
3695         case CERT_ALT_NAME_DNS_NAME:
3696         case CERT_ALT_NAME_EDI_PARTY_NAME:
3697         case CERT_ALT_NAME_URL:
3698         case CERT_ALT_NAME_REGISTERED_ID:
3699             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3700              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3701              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3702              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3703              "Unexpected name\n");
3704             break;
3705         case CERT_ALT_NAME_X400_ADDRESS:
3706         case CERT_ALT_NAME_DIRECTORY_NAME:
3707         case CERT_ALT_NAME_IP_ADDRESS:
3708             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3709                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3710             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3711                        U(*got).IPAddress.cbData), "Unexpected value\n");
3712             break;
3713         }
3714     }
3715 }
3716
3717 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3718  const CERT_ALT_NAME_INFO *got)
3719 {
3720     DWORD i;
3721
3722     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3723      expected->cAltEntry, got->cAltEntry);
3724     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3725         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3726 }
3727
3728 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3729  const CRL_DIST_POINT_NAME *got)
3730 {
3731     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3732      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3733     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3734         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3735 }
3736
3737 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3738  const CRL_ISSUING_DIST_POINT *got)
3739 {
3740     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3741     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3742      "Unexpected fOnlyContainsUserCerts\n");
3743     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3744      "Unexpected fOnlyContainsCACerts\n");
3745     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3746      "Unexpected reason flags\n");
3747     ok(got->fIndirectCRL == expected->fIndirectCRL,
3748      "Unexpected fIndirectCRL\n");
3749 }
3750
3751 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3752 {
3753     BOOL ret;
3754     BYTE *buf = NULL;
3755     DWORD size = 0;
3756     CRL_ISSUING_DIST_POINT point = { { 0 } };
3757
3758     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3759      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3760      &buf, &size);
3761     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3762     {
3763         skip("no X509_ISSUING_DIST_POINT decode support\n");
3764         return;
3765     }
3766     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3767     if (ret)
3768     {
3769         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3770         LocalFree(buf);
3771     }
3772     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3773      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3774      &buf, &size);
3775     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3776     if (ret)
3777     {
3778         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3779         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3780         LocalFree(buf);
3781     }
3782     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3783      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3784      &buf, &size);
3785     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3786     if (ret)
3787     {
3788         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3789         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3790         U(point.DistPointName).FullName.cAltEntry = 0;
3791         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3792         LocalFree(buf);
3793     }
3794     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3795      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3796     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3797     if (ret)
3798     {
3799         CERT_ALT_NAME_ENTRY entry;
3800
3801         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3802         U(entry).pwszURL = (LPWSTR)url;
3803         U(point.DistPointName).FullName.cAltEntry = 1;
3804         U(point.DistPointName).FullName.rgAltEntry = &entry;
3805         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3806         LocalFree(buf);
3807     }
3808 }
3809
3810 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3811  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3812  0x30, 0x5a };
3813 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3814  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3815  0x30, 0x30, 0x30, 0x30, 0x5a };
3816 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3817  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3818  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3819  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3820  0x5a };
3821 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3822  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3823  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3824  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3825  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3826  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3827 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3828  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3829  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3830  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3831  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3832  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3833 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3834  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3835  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3836  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3837  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3838  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3839  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3840 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3841  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3842  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3843  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3844  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3845  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3846  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3847 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3848  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3849  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3850  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3851  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3852  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3853  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3854
3855 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3856 {
3857     BOOL ret;
3858     BYTE *buf = NULL;
3859     DWORD size = 0;
3860     CRL_INFO info = { 0 };
3861     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3862
3863     /* Test with a V1 CRL */
3864     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3865      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3866     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3867      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3868     if (buf)
3869     {
3870         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3871         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3872         LocalFree(buf);
3873     }
3874     /* Test v2 CRL */
3875     info.dwVersion = CRL_V2;
3876     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3877      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3878     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3879      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3880     if (buf)
3881     {
3882         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3883          v2CRL[1] + 2, size);
3884         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3885         LocalFree(buf);
3886     }
3887     /* v1 CRL with a name */
3888     info.dwVersion = CRL_V1;
3889     info.Issuer.cbData = sizeof(encodedCommonName);
3890     info.Issuer.pbData = (BYTE *)encodedCommonName;
3891     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3892      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3893     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3894     if (buf)
3895     {
3896         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3897         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3898         LocalFree(buf);
3899     }
3900     if (0)
3901     {
3902         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3903         info.cCRLEntry = 1;
3904         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3905          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3906         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3907          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3908     }
3909     /* now set an empty entry */
3910     info.cCRLEntry = 1;
3911     info.rgCRLEntry = &entry;
3912     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3913      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3914     if (buf)
3915     {
3916         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3917          "Wrong size %d\n", size);
3918         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3919          "Got unexpected value\n");
3920         LocalFree(buf);
3921     }
3922     /* an entry with a serial number */
3923     entry.SerialNumber.cbData = sizeof(serialNum);
3924     entry.SerialNumber.pbData = (BYTE *)serialNum;
3925     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3926      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3927     if (buf)
3928     {
3929         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3930          "Wrong size %d\n", size);
3931         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3932          "Got unexpected value\n");
3933         LocalFree(buf);
3934     }
3935     /* an entry with an extension */
3936     entry.cExtension = 1;
3937     entry.rgExtension = &criticalExt;
3938     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3939      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3940     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3941     if (buf)
3942     {
3943         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3944         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3945         LocalFree(buf);
3946     }
3947     /* a CRL with an extension */
3948     entry.cExtension = 0;
3949     info.cExtension = 1;
3950     info.rgExtension = &criticalExt;
3951     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3952      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3953     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3954     if (buf)
3955     {
3956         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3957         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3958         LocalFree(buf);
3959     }
3960     /* a v2 CRL with an extension, this time non-critical */
3961     info.dwVersion = CRL_V2;
3962     info.rgExtension = &nonCriticalExt;
3963     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3964      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3965     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3966     if (buf)
3967     {
3968         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3969         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3970         LocalFree(buf);
3971     }
3972 }
3973
3974 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3975  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3976  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3977  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3978  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3979  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3980  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3981  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3982  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3983  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3984  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3985  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3986  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3987  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3988  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3989  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3990  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3991  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3992  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3993  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3994  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3995  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3996  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3997  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3998  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3999  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4000  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4001  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4002  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4003  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4004  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4005  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4006  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4007  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4008  0xcd };
4009 static const BYTE verisignCRLWithLotsOfEntries[] = {
4010 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4011 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4012 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4013 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4014 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4015 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4016 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4017 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4018 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4019 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4020 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4021 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4022 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4023 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4024 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4025 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4026 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4027 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4028 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4029 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4030 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4031 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4032 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4033 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4034 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4035 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4036 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4037 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4038 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4039 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4040 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4041 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4042 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4043 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4044 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4045 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4046 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4047 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4048 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4049 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4050 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4051 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4052 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4053 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4054 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4055 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4056 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4057 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4058 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4059 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4060 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4061 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4062 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4063 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4064 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4065 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4066 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4067 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4068 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4069 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4070 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4071 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4072 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4073 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4074 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4075 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4076 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4077 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4078 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4079 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4080 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4081 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4082 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4083 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4084 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4085 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4086 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4087 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4088 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4089 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4090 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4091 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4092 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4093 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4094 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4095 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4096 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4097 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4098 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4099 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4100 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4101 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4102 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4103 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4104 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4105 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4106 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4107 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4108 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4109 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4110 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4111 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4112 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4113 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4114 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4115 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4116 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4117 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4118 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4119 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4120 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4121 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4122 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4123 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4124 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4125 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4126 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4127 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4128 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4129 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4130 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4131 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4132 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4133 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4134 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4135 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4136 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4137 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4138 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4139 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4140 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4141 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4142 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4143 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4144 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4145 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4146 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4147 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4148 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4149 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4150 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4151 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4152 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4153 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4154 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4155 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4156 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4157 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4158 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4159 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4160 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4161 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4162 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4163 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4164 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4165 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4166 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4167 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4168 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4169 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4170 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4171 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4172 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4173 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4174 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4175 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4176 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4177 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4178 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4179 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4180 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4181 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4182 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4183 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4184 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4185 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4186 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4187 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4188 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4189 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4190 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4191 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4192 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4193 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4194 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4195 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4196 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4197 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4198 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4199 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4200 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4201 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4202 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4203 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4204 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4205 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4206 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4207 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4208 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4209 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4210 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4211 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4212 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4213 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4214 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4215 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4216 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4217 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4218 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4219 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4220 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4221 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4222 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4223 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4224 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4225 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4226 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4227 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4228 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4229 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4230 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4231 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4232 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4233 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4234 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4235 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4236 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4237 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4238 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4239 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4240 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4241 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4242 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4243 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4244 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4245 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4246 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4247 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4248 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4249 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4250 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4251 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4252 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4253 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4254 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4255 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4256 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4257 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4258 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4259 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4260 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4261 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4262 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4263 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4264 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4265 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4266 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4267 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4268 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4269 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4270 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4271 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4272 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4273 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4274 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4275 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4276 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4277 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4278 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4279 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4280 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4281 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4282 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4283 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4284 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4285 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4286 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4287 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4288 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4289 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4290 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4291 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4292 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4293 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4294 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4295 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4296 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4297 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4298 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4299 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4300 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4301 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4302 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4303 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4304 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4305 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4306 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4307 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4308 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4309 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4310 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4311 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4312 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4313 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4314 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4315 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4316 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4317 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4318 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4319 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4320 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4321 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4322 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4323 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4324 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4325 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4326 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4327 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4328 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4329 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4330 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4331 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4332 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4333 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4334 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4335 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4336 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4337 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4338 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4339 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4340 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4341 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4342 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4343 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4344 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4345 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4346 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4347 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4348 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4349 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4350 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4351 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4352 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4353 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4354 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4355 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4356 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4357 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4358 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4359 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4360 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4361 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4362 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4363 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4364 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4365 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4366 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4367 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4368 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4369 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4370 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4371 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4372 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4373 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4374 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4375 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4376 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4377 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4378 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4379 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4380 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4381 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4382 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4383 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4384 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4385 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4386 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4387 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4388 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4389 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4390 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4391 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4392 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4393 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4394 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4395 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4396 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4397 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4398 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4399 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4400 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4401 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4402 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4403 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4404 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4405 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4406 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4407 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4408 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4409 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4410 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4411 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4412 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4413 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4414 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4415 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4416 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4417 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4418 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4419 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4420 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4421 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4422 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4423 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4424 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4425 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4426 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4427 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4428 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4429 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4430 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4431 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4432 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4433 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4434 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4435 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4436 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4437 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4438 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4439 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4440 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4441 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4442 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4443 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4444 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4445 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4446 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4447 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4448 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4449 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4450 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4451 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4452 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4453 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4454 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4455 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4456 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4457 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4458 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4459 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4460 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4461 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4462 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4463 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4464 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4465 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4466 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4467 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4468 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4469 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4470 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4471 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4472 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4473 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4474 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4475 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4476 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4477 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4478 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4479 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4480 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4481 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4482 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4483 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4484 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4485 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4486 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4487 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4488 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4489 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4490 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4491 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4492 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4493 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4494 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4495 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4496 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4497 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4498 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4499 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4500 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4501 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4502 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4503 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4504 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4505 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4506 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4507 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4508 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4509 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4510 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4511 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4512 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4513 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4514 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4515 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4516 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4517 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4518
4519 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4520 {
4521     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4522     BOOL ret;
4523     BYTE *buf = NULL;
4524     DWORD size = 0, i;
4525
4526     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4527     {
4528         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4529          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4530          &buf, &size);
4531         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4532          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4533          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4534          GetLastError());
4535     }
4536     /* at a minimum, a CRL must contain an issuer: */
4537     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4538      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4539      &buf, &size);
4540     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4541     if (buf)
4542     {
4543         CRL_INFO *info = (CRL_INFO *)buf;
4544
4545         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4546         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4547          info->cCRLEntry);
4548         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4549          "Wrong issuer size %d\n", info->Issuer.cbData);
4550         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4551          "Unexpected issuer\n");
4552         LocalFree(buf);
4553     }
4554     /* check decoding with an empty CRL entry */
4555     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4556      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4557      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4558     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4559      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4560      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4561      GetLastError());
4562     /* with a real CRL entry */
4563     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4564      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4565      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4566     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4567     if (buf)
4568     {
4569         CRL_INFO *info = (CRL_INFO *)buf;
4570         CRL_ENTRY *entry;
4571
4572         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4573         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4574          info->cCRLEntry);
4575         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4576         entry = info->rgCRLEntry;
4577         ok(entry->SerialNumber.cbData == 1,
4578          "Expected serial number size 1, got %d\n",
4579          entry->SerialNumber.cbData);
4580         ok(*entry->SerialNumber.pbData == *serialNum,
4581          "Expected serial number %d, got %d\n", *serialNum,
4582          *entry->SerialNumber.pbData);
4583         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4584          "Wrong issuer size %d\n", info->Issuer.cbData);
4585         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4586          "Unexpected issuer\n");
4587         LocalFree(buf);
4588     }
4589     /* a real CRL from verisign that has extensions */
4590     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4591      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4592      NULL, &buf, &size);
4593     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4594     if (buf)
4595     {
4596         CRL_INFO *info = (CRL_INFO *)buf;
4597         CRL_ENTRY *entry;
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         entry = info->rgCRLEntry;
4604         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4605          info->cExtension);
4606         LocalFree(buf);
4607     }
4608     /* another real CRL from verisign that has lots of entries */
4609     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4610      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4611      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4612     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4613     if (buf)
4614     {
4615         CRL_INFO *info = (CRL_INFO *)buf;
4616
4617         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4618         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4619          info->cCRLEntry);
4620         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4621          info->cExtension);
4622         LocalFree(buf);
4623     }
4624     /* and finally, with an extension */
4625     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4626      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4627      NULL, &buf, &size);
4628     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4629     if (buf)
4630     {
4631         CRL_INFO *info = (CRL_INFO *)buf;
4632         CRL_ENTRY *entry;
4633
4634         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4635         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4636          info->cCRLEntry);
4637         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4638         entry = info->rgCRLEntry;
4639         ok(entry->SerialNumber.cbData == 1,
4640          "Expected serial number size 1, got %d\n",
4641          entry->SerialNumber.cbData);
4642         ok(*entry->SerialNumber.pbData == *serialNum,
4643          "Expected serial number %d, got %d\n", *serialNum,
4644          *entry->SerialNumber.pbData);
4645         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4646          "Wrong issuer size %d\n", info->Issuer.cbData);
4647         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4648          "Unexpected issuer\n");
4649         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4650          info->cExtension);
4651         LocalFree(buf);
4652     }
4653     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4654      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4655      NULL, &buf, &size);
4656     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4657     if (buf)
4658     {
4659         CRL_INFO *info = (CRL_INFO *)buf;
4660
4661         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4662          info->cExtension);
4663         LocalFree(buf);
4664     }
4665 }
4666
4667 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4668  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4669 static const BYTE encodedUsage[] = {
4670  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4671  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4672  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4673
4674 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4675 {
4676     BOOL ret;
4677     BYTE *buf = NULL;
4678     DWORD size = 0;
4679     CERT_ENHKEY_USAGE usage;
4680
4681     /* Test with empty usage */
4682     usage.cUsageIdentifier = 0;
4683     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4684      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4685     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4686     if (buf)
4687     {
4688         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4689         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4690         LocalFree(buf);
4691     }
4692     /* Test with a few usages */
4693     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4694     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4695     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4696      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4697     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4698     if (buf)
4699     {
4700         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4701         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4702         LocalFree(buf);
4703     }
4704 }
4705
4706 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4707 {
4708     BOOL ret;
4709     LPBYTE buf = NULL;
4710     DWORD size = 0;
4711
4712     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4713      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4714      &buf, &size);
4715     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4716     if (buf)
4717     {
4718         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4719
4720         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4721          "Wrong size %d\n", size);
4722         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4723          usage->cUsageIdentifier);
4724         LocalFree(buf);
4725     }
4726     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4727      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4728      &buf, &size);
4729     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4730     if (buf)
4731     {
4732         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4733         DWORD i;
4734
4735         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4736          "Wrong size %d\n", size);
4737         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4738          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4739         for (i = 0; i < usage->cUsageIdentifier; i++)
4740             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4741              "Expected OID %s, got %s\n", keyUsages[i],
4742              usage->rgpszUsageIdentifier[i]);
4743         LocalFree(buf);
4744     }
4745 }
4746
4747 static BYTE keyId[] = { 1,2,3,4 };
4748 static const BYTE authorityKeyIdWithId[] = {
4749  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4750 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4751  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4752  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4753 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4754
4755 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4756 {
4757     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4758     BOOL ret;
4759     BYTE *buf = NULL;
4760     DWORD size = 0;
4761
4762     /* Test with empty id */
4763     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4764      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4765     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4766     if (buf)
4767     {
4768         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4769         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4770         LocalFree(buf);
4771     }
4772     /* With just a key id */
4773     info.KeyId.cbData = sizeof(keyId);
4774     info.KeyId.pbData = keyId;
4775     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4776      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4777     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4778     if (buf)
4779     {
4780         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4781         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4782         LocalFree(buf);
4783     }
4784     /* With just an issuer */
4785     info.KeyId.cbData = 0;
4786     info.CertIssuer.cbData = sizeof(encodedCommonName);
4787     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4788     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4791     if (buf)
4792     {
4793         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4794          size);
4795         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4796         LocalFree(buf);
4797     }
4798     /* With just a serial number */
4799     info.CertIssuer.cbData = 0;
4800     info.CertSerialNumber.cbData = sizeof(serialNum);
4801     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4802     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4803      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4804     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4805     if (buf)
4806     {
4807         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4808          size);
4809         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4810         LocalFree(buf);
4811     }
4812 }
4813
4814 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4815 {
4816     BOOL ret;
4817     LPBYTE buf = NULL;
4818     DWORD size = 0;
4819
4820     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4821      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4822      &buf, &size);
4823     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4824     if (buf)
4825     {
4826         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4827
4828         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4829          size);
4830         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4831         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4832         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4833         LocalFree(buf);
4834     }
4835     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4836      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4837      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4838     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4839     if (buf)
4840     {
4841         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4842
4843         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4844          size);
4845         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4846         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4847          "Unexpected key id\n");
4848         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4849         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4850         LocalFree(buf);
4851     }
4852     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4853      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4854      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4855     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4856     if (buf)
4857     {
4858         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4859
4860         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4861          size);
4862         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4863         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4864          "Unexpected issuer len\n");
4865         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4866          sizeof(encodedCommonName)), "Unexpected issuer\n");
4867         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4868         LocalFree(buf);
4869     }
4870     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4871      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4872      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4873     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4874     if (buf)
4875     {
4876         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4877
4878         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4879          size);
4880         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4881         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4882         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4883          "Unexpected serial number len\n");
4884         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4885          "Unexpected serial number\n");
4886         LocalFree(buf);
4887     }
4888 }
4889
4890 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4891  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4892  0x6f,0x72,0x67 };
4893
4894 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4895 {
4896     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4897     CERT_ALT_NAME_ENTRY entry = { 0 };
4898     BOOL ret;
4899     BYTE *buf = NULL;
4900     DWORD size = 0;
4901
4902     /* Test with empty id */
4903     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4904      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4905     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4906     if (buf)
4907     {
4908         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4909         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4910         LocalFree(buf);
4911     }
4912     /* With just a key id */
4913     info.KeyId.cbData = sizeof(keyId);
4914     info.KeyId.pbData = keyId;
4915     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4918     if (buf)
4919     {
4920         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4921          size);
4922         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4923         LocalFree(buf);
4924     }
4925     /* With a bogus issuer name */
4926     info.KeyId.cbData = 0;
4927     info.AuthorityCertIssuer.cAltEntry = 1;
4928     info.AuthorityCertIssuer.rgAltEntry = &entry;
4929     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4930      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4931     ok(!ret && GetLastError() == E_INVALIDARG,
4932      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4933     /* With an issuer name */
4934     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4935     U(entry).pwszURL = (LPWSTR)url;
4936     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4937      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4938     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4939     if (buf)
4940     {
4941         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4942          size);
4943         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4944          "Unexpected value\n");
4945         LocalFree(buf);
4946     }
4947     /* With just a serial number */
4948     info.AuthorityCertIssuer.cAltEntry = 0;
4949     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4950     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4951     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4952      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4953     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4954     if (buf)
4955     {
4956         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4957          size);
4958         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4959         LocalFree(buf);
4960     }
4961 }
4962
4963 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4964 {
4965     BOOL ret;
4966     LPBYTE buf = NULL;
4967     DWORD size = 0;
4968
4969     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4970      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4971      &buf, &size);
4972     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4973     if (buf)
4974     {
4975         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4976
4977         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4978          size);
4979         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4980         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4981          "Expected no issuer name entries\n");
4982         ok(info->AuthorityCertSerialNumber.cbData == 0,
4983          "Expected no serial number\n");
4984         LocalFree(buf);
4985     }
4986     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4987      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4988      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4989     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4990     if (buf)
4991     {
4992         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4993
4994         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4995          size);
4996         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4997         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4998          "Unexpected key id\n");
4999         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5000          "Expected no issuer name entries\n");
5001         ok(info->AuthorityCertSerialNumber.cbData == 0,
5002          "Expected no serial number\n");
5003         LocalFree(buf);
5004     }
5005     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5006      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5007      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5008     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5009     if (buf)
5010     {
5011         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5012
5013         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5014          size);
5015         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5016         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5017          "Expected 1 issuer entry, got %d\n",
5018          info->AuthorityCertIssuer.cAltEntry);
5019         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5020          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5021          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5022         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5023          url), "Unexpected URL\n");
5024         ok(info->AuthorityCertSerialNumber.cbData == 0,
5025          "Expected no serial number\n");
5026         LocalFree(buf);
5027     }
5028     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5029      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5030      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5031     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5032     if (buf)
5033     {
5034         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5035
5036         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5037          size);
5038         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5039         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5040          "Expected no issuer name entries\n");
5041         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5042          "Unexpected serial number len\n");
5043         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5044          sizeof(serialNum)), "Unexpected serial number\n");
5045         LocalFree(buf);
5046     }
5047 }
5048
5049 static const BYTE authorityInfoAccessWithUrl[] = {
5050 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5051 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5052 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5053 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5054 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5055 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5056
5057 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5058 {
5059     static char oid1[] = "1.2.3";
5060     static char oid2[] = "1.5.6";
5061     BOOL ret;
5062     BYTE *buf = NULL;
5063     DWORD size = 0;
5064     CERT_ACCESS_DESCRIPTION accessDescription[2];
5065     CERT_AUTHORITY_INFO_ACCESS aia;
5066
5067     memset(accessDescription, 0, sizeof(accessDescription));
5068     aia.cAccDescr = 0;
5069     aia.rgAccDescr = NULL;
5070     /* Having no access descriptions is allowed */
5071     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5072      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5073     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5074     if (buf)
5075     {
5076         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5077         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5078         LocalFree(buf);
5079         buf = NULL;
5080     }
5081     /* It can't have an empty access method */
5082     aia.cAccDescr = 1;
5083     aia.rgAccDescr = accessDescription;
5084     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5085      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5086     ok(!ret && (GetLastError() == E_INVALIDARG ||
5087      GetLastError() == OSS_LIMITED /* Win9x */),
5088      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5089     /* It can't have an empty location */
5090     accessDescription[0].pszAccessMethod = oid1;
5091     SetLastError(0xdeadbeef);
5092     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5093      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5094     ok(!ret && GetLastError() == E_INVALIDARG,
5095      "expected E_INVALIDARG, got %08x\n", GetLastError());
5096     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5097     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5098     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5099      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5100     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5101     if (buf)
5102     {
5103         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5104          size);
5105         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5106          "unexpected value\n");
5107         LocalFree(buf);
5108         buf = NULL;
5109     }
5110     accessDescription[1].pszAccessMethod = oid2;
5111     accessDescription[1].AccessLocation.dwAltNameChoice =
5112      CERT_ALT_NAME_IP_ADDRESS;
5113     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5114      sizeof(encodedIPAddr);
5115     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5116      (LPBYTE)encodedIPAddr;
5117     aia.cAccDescr = 2;
5118     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5119      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5120     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5121     if (buf)
5122     {
5123         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5124          "unexpected size %d\n", size);
5125         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5126          "unexpected value\n");
5127         LocalFree(buf);
5128         buf = NULL;
5129     }
5130 }
5131
5132 static void compareAuthorityInfoAccess(LPCSTR header,
5133  const CERT_AUTHORITY_INFO_ACCESS *expected,
5134  const CERT_AUTHORITY_INFO_ACCESS *got)
5135 {
5136     DWORD i;
5137
5138     ok(expected->cAccDescr == got->cAccDescr,
5139      "%s: expected %d access descriptions, got %d\n", header,
5140      expected->cAccDescr, got->cAccDescr);
5141     for (i = 0; i < expected->cAccDescr; i++)
5142     {
5143         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5144          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5145          header, i, expected->rgAccDescr[i].pszAccessMethod,
5146          got->rgAccDescr[i].pszAccessMethod);
5147         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5148          &got->rgAccDescr[i].AccessLocation);
5149     }
5150 }
5151
5152 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5153 {
5154     static char oid1[] = "1.2.3";
5155     static char oid2[] = "1.5.6";
5156     BOOL ret;
5157     LPBYTE buf = NULL;
5158     DWORD size = 0;
5159
5160     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5161      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5162      &buf, &size);
5163     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5164     if (buf)
5165     {
5166         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5167
5168         compareAuthorityInfoAccess("empty AIA", &aia,
5169          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5170         LocalFree(buf);
5171         buf = NULL;
5172     }
5173     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5174      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5175      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5176     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5177     if (buf)
5178     {
5179         CERT_ACCESS_DESCRIPTION accessDescription;
5180         CERT_AUTHORITY_INFO_ACCESS aia;
5181
5182         accessDescription.pszAccessMethod = oid1;
5183         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5184         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5185         aia.cAccDescr = 1;
5186         aia.rgAccDescr = &accessDescription;
5187         compareAuthorityInfoAccess("AIA with URL", &aia,
5188          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5189         LocalFree(buf);
5190         buf = NULL;
5191     }
5192     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5193      authorityInfoAccessWithUrlAndIPAddr,
5194      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5195      NULL, &buf, &size);
5196     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5197     if (buf)
5198     {
5199         CERT_ACCESS_DESCRIPTION accessDescription[2];
5200         CERT_AUTHORITY_INFO_ACCESS aia;
5201
5202         accessDescription[0].pszAccessMethod = oid1;
5203         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5204         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5205         accessDescription[1].pszAccessMethod = oid2;
5206         accessDescription[1].AccessLocation.dwAltNameChoice =
5207          CERT_ALT_NAME_IP_ADDRESS;
5208         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5209          sizeof(encodedIPAddr);
5210         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5211          (LPBYTE)encodedIPAddr;
5212         aia.cAccDescr = 2;
5213         aia.rgAccDescr = accessDescription;
5214         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5215          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5216         LocalFree(buf);
5217         buf = NULL;
5218     }
5219 }
5220
5221 static const BYTE emptyCTL[] = {
5222 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5223 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5224 static const BYTE emptyCTLWithVersion1[] = {
5225 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5226 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5227 static const BYTE ctlWithUsageIdentifier[] = {
5228 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5229 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5230 static const BYTE ctlWithListIdentifier[] = {
5231 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5232 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5233 static const BYTE ctlWithSequenceNumber[] = {
5234 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5235 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5236 static const BYTE ctlWithThisUpdate[] = {
5237 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5238 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5239 static const BYTE ctlWithThisAndNextUpdate[] = {
5240 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5241 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5242 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5243 static const BYTE ctlWithAlgId[] = {
5244 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5245 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5246 static const BYTE ctlWithBogusEntry[] = {
5247 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5248 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5249 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5250 static const BYTE ctlWithOneEntry[] = {
5251 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5252 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5253 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5254 static const BYTE ctlWithTwoEntries[] = {
5255 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5256 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5257 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5258 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5259 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5260
5261 static void test_encodeCTL(DWORD dwEncoding)
5262 {
5263     static char oid1[] = "1.2.3";
5264     static char oid2[] = "1.5.6";
5265     char *pOid1 = oid1;
5266     BOOL ret;
5267     BYTE *buf = NULL;
5268     DWORD size = 0;
5269     CTL_INFO info;
5270     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5271     CTL_ENTRY ctlEntry[2];
5272     CRYPT_ATTRIBUTE attr1, attr2;
5273     CRYPT_ATTR_BLOB value1, value2;
5274
5275     memset(&info, 0, sizeof(info));
5276     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5277      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5278     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5279     if (buf)
5280     {
5281         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5282         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5283         LocalFree(buf);
5284         buf = NULL;
5285     }
5286     info.dwVersion = 1;
5287     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5288      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5289     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5290     if (buf)
5291     {
5292         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5293         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5294         LocalFree(buf);
5295         buf = NULL;
5296     }
5297     info.dwVersion = 0;
5298     info.SubjectUsage.cUsageIdentifier = 1;
5299     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5300     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5301      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5302     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5303     if (buf)
5304     {
5305         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5306          size);
5307         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5308         LocalFree(buf);
5309         buf = NULL;
5310     }
5311     info.SubjectUsage.cUsageIdentifier = 0;
5312     info.ListIdentifier.cbData = sizeof(serialNum);
5313     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5314     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5315      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5316     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5317     if (buf)
5318     {
5319         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5320         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5321         LocalFree(buf);
5322         buf = NULL;
5323     }
5324     info.ListIdentifier.cbData = 0;
5325     info.SequenceNumber.cbData = sizeof(serialNum);
5326     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5327     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5328      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5329     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5330     if (buf)
5331     {
5332         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5333          size);
5334         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5335         LocalFree(buf);
5336         buf = NULL;
5337     }
5338     info.SequenceNumber.cbData = 0;
5339     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5340     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5341      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5342     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5343     if (buf)
5344     {
5345         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5346         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5347         LocalFree(buf);
5348         buf = NULL;
5349     }
5350     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5351     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5352      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5353     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5354     if (buf)
5355     {
5356         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5357          size);
5358         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5359         LocalFree(buf);
5360         buf = NULL;
5361     }
5362     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5363     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5364     info.SubjectAlgorithm.pszObjId = oid2;
5365     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5366      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5367     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5368     if (buf)
5369     {
5370         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5371         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5372         LocalFree(buf);
5373         buf = NULL;
5374     }
5375     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5376      * (see tests below) but it'll encode fine.
5377      */
5378     info.SubjectAlgorithm.pszObjId = NULL;
5379     value1.cbData = sizeof(serialNum);
5380     value1.pbData = (LPBYTE)serialNum;
5381     attr1.pszObjId = oid1;
5382     attr1.cValue = 1;
5383     attr1.rgValue = &value1;
5384     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5385     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5386     ctlEntry[0].cAttribute = 1;
5387     ctlEntry[0].rgAttribute = &attr1;
5388     info.cCTLEntry = 1;
5389     info.rgCTLEntry = ctlEntry;
5390     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5391      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5392     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5393     if (buf)
5394     {
5395         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5396         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5397         LocalFree(buf);
5398         buf = NULL;
5399     }
5400     value1.cbData = sizeof(emptySequence);
5401     value1.pbData = (LPBYTE)emptySequence;
5402     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5403      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5404     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5405     if (buf)
5406     {
5407         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5408         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5409         LocalFree(buf);
5410         buf = NULL;
5411     }
5412     value2.cbData = sizeof(encodedIPAddr);
5413     value2.pbData = (LPBYTE)encodedIPAddr;
5414     attr2.pszObjId = oid2;
5415     attr2.cValue = 1;
5416     attr2.rgValue = &value2;
5417     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5418     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5419     ctlEntry[1].cAttribute = 1;
5420     ctlEntry[1].rgAttribute = &attr2;
5421     info.cCTLEntry = 2;
5422     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5423      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5424     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5425     if (buf)
5426     {
5427         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5428         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5429         LocalFree(buf);
5430         buf = NULL;
5431     }
5432 }
5433
5434 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5435  const CTL_INFO *got)
5436 {
5437     DWORD i, j, k;
5438
5439     ok(expected->dwVersion == got->dwVersion,
5440      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5441      got->dwVersion);
5442     ok(expected->SubjectUsage.cUsageIdentifier ==
5443      got->SubjectUsage.cUsageIdentifier,
5444      "%s: expected %d usage identifiers, got %d\n", header,
5445      expected->SubjectUsage.cUsageIdentifier,
5446      got->SubjectUsage.cUsageIdentifier);
5447     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5448         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5449          got->SubjectUsage.rgpszUsageIdentifier[i]),
5450          "%s[%d]: expected %s, got %s\n", header, i,
5451          expected->SubjectUsage.rgpszUsageIdentifier[i],
5452          got->SubjectUsage.rgpszUsageIdentifier[i]);
5453     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5454      "%s: expected list identifier of %d bytes, got %d\n", header,
5455      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5456     if (expected->ListIdentifier.cbData)
5457         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5458          expected->ListIdentifier.cbData),
5459          "%s: unexpected list identifier value\n", header);
5460     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5461      "%s: expected sequence number of %d bytes, got %d\n", header,
5462      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5463     if (expected->SequenceNumber.cbData)
5464         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5465          expected->SequenceNumber.cbData),
5466          "%s: unexpected sequence number value\n", header);
5467     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5468      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5469      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5470      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5471     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5472      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5473      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5474      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5475     if (expected->SubjectAlgorithm.pszObjId &&
5476      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5477         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5478          expected->SubjectAlgorithm.pszObjId);
5479     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5480         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5481          got->SubjectAlgorithm.pszObjId),
5482          "%s: expected subject algorithm %s, got %s\n", header,
5483          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5484     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5485      got->SubjectAlgorithm.Parameters.cbData,
5486      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5487      expected->SubjectAlgorithm.Parameters.cbData,
5488      got->SubjectAlgorithm.Parameters.cbData);
5489     if (expected->SubjectAlgorithm.Parameters.cbData)
5490         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5491          got->SubjectAlgorithm.Parameters.pbData,
5492          expected->SubjectAlgorithm.Parameters.cbData),
5493          "%s: unexpected subject algorithm parameter value\n", header);
5494     ok(expected->cCTLEntry == got->cCTLEntry,
5495      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5496      got->cCTLEntry);
5497     for (i = 0; i < expected->cCTLEntry; i++)
5498     {
5499         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5500          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5501          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5502          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5503          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5504         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5505             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5506              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5507              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5508              "%s[%d]: unexpected subject identifier value\n",
5509              header, i);
5510         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5511         {
5512             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5513              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5514              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5515              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5516              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5517             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5518             {
5519                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5520                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5521                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5522                  header, i, j, k,
5523                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5524                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5525                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5526                     ok(!memcmp(
5527                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5528                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5529                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5530                      "%s[%d][%d][%d]: unexpected value\n",
5531                      header, i, j, k);
5532             }
5533         }
5534     }
5535     ok(expected->cExtension == got->cExtension,
5536      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5537      got->cExtension);
5538     for (i = 0; i < expected->cExtension; i++)
5539     {
5540         ok(!strcmp(expected->rgExtension[i].pszObjId,
5541          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5542          header, i, expected->rgExtension[i].pszObjId,
5543          got->rgExtension[i].pszObjId);
5544         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5545          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5546          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5547         ok(expected->rgExtension[i].Value.cbData ==
5548          got->rgExtension[i].Value.cbData,
5549          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5550          header, i, expected->rgExtension[i].Value.cbData,
5551          got->rgExtension[i].Value.cbData);
5552         if (expected->rgExtension[i].Value.cbData)
5553             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5554              got->rgExtension[i].Value.pbData,
5555              expected->rgExtension[i].Value.cbData),
5556              "%s[%d]: unexpected extension value\n", header, i);
5557     }
5558 }
5559
5560 static const BYTE signedCTL[] = {
5561 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5562 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5563 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5564 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5565 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5566 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5567 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5568 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5569 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5570 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5571 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5572 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5573 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5574 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5575 static const BYTE signedCTLWithCTLInnerContent[] = {
5576 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5577 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5578 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5579 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5580 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5581 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5582 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5583 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5584 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5585 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5586 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5587 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5588 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5589 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5590 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5591 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5592 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5593 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5594 0x57,0x6c,0x0b,0x47,0xb8 };
5595
5596 static void test_decodeCTL(DWORD dwEncoding)
5597 {
5598     static char oid1[] = "1.2.3";
5599     static char oid2[] = "1.5.6";
5600     static BYTE nullData[] = { 5,0 };
5601     char *pOid1 = oid1;
5602     BOOL ret;
5603     BYTE *buf = NULL;
5604     DWORD size = 0;
5605     CTL_INFO info;
5606     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5607     CTL_ENTRY ctlEntry[2];
5608     CRYPT_ATTRIBUTE attr1, attr2;
5609     CRYPT_ATTR_BLOB value1, value2;
5610
5611     memset(&info, 0, sizeof(info));
5612     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5613      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5614     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5615     if (buf)
5616     {
5617         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5618         LocalFree(buf);
5619         buf = NULL;
5620     }
5621     info.dwVersion = 1;
5622     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5623      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5624      &size);
5625     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5626     if (buf)
5627     {
5628         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5629         LocalFree(buf);
5630         buf = NULL;
5631     }
5632     info.dwVersion = 0;
5633     info.SubjectUsage.cUsageIdentifier = 1;
5634     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5635     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5636      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5637      &buf, &size);
5638     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5639     if (buf)
5640     {
5641         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5642         LocalFree(buf);
5643         buf = NULL;
5644     }
5645     info.SubjectUsage.cUsageIdentifier = 0;
5646     info.ListIdentifier.cbData = sizeof(serialNum);
5647     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5648     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5649      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5650     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5651     if (buf)
5652     {
5653         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5654         LocalFree(buf);
5655         buf = NULL;
5656     }
5657     info.ListIdentifier.cbData = 0;
5658     info.SequenceNumber.cbData = sizeof(serialNum);
5659     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5660     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5661      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5662     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5663     if (buf)
5664     {
5665         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5666         LocalFree(buf);
5667         buf = NULL;
5668     }
5669     info.SequenceNumber.cbData = 0;
5670     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5671     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5672      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5673     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5674     if (buf)
5675     {
5676         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5677         LocalFree(buf);
5678         buf = NULL;
5679     }
5680     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5681     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5682      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5683      &buf, &size);
5684     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5685     if (buf)
5686     {
5687         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5688         LocalFree(buf);
5689         buf = NULL;
5690     }
5691     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5692     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5693     info.SubjectAlgorithm.pszObjId = oid2;
5694     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5695     info.SubjectAlgorithm.Parameters.pbData = nullData;
5696     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5697      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5698     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5699     if (buf)
5700     {
5701         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5702         LocalFree(buf);
5703         buf = NULL;
5704     }
5705     SetLastError(0xdeadbeef);
5706     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5707      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5708     ok(!ret &&
5709      (GetLastError() == CRYPT_E_ASN1_EOD ||
5710       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5711       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5712      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5713      GetLastError());
5714     info.SubjectAlgorithm.Parameters.cbData = 0;
5715     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5716     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5717     info.SubjectAlgorithm.pszObjId = oid2;
5718     info.SubjectAlgorithm.pszObjId = NULL;
5719     value1.cbData = sizeof(emptySequence);
5720     value1.pbData = (LPBYTE)emptySequence;
5721     attr1.pszObjId = oid1;
5722     attr1.cValue = 1;
5723     attr1.rgValue = &value1;
5724     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5725     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5726     ctlEntry[0].cAttribute = 1;
5727     ctlEntry[0].rgAttribute = &attr1;
5728     info.cCTLEntry = 1;
5729     info.rgCTLEntry = ctlEntry;
5730     SetLastError(0xdeadbeef);
5731     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5732      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5733     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5734     if (buf)
5735     {
5736         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5737         LocalFree(buf);
5738         buf = NULL;
5739     }
5740     value2.cbData = sizeof(encodedIPAddr);
5741     value2.pbData = (LPBYTE)encodedIPAddr;
5742     attr2.pszObjId = oid2;
5743     attr2.cValue = 1;
5744     attr2.rgValue = &value2;
5745     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5746     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5747     ctlEntry[1].cAttribute = 1;
5748     ctlEntry[1].rgAttribute = &attr2;
5749     info.cCTLEntry = 2;
5750     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5751      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5752     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5753     if (buf)
5754     {
5755         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5756         LocalFree(buf);
5757         buf = NULL;
5758     }
5759     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5760     SetLastError(0xdeadbeef);
5761     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5762      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5763     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5764      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5765      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5766      GetLastError());
5767     SetLastError(0xdeadbeef);
5768     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5769      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5770      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5771     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5772      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5773      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5774      GetLastError());
5775 }
5776
5777 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5778 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5779  0x03,0,0,0,0,0,0 };
5780 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5781  0xa0,0x01,0x01 };
5782 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5783  0x03,0x02,0x01,0x01 };
5784 static BYTE bogusDER[] = { 1 };
5785
5786 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5787 {
5788     BOOL ret;
5789     BYTE *buf = NULL;
5790     DWORD size = 0;
5791     CRYPT_CONTENT_INFO info = { 0 };
5792     char oid1[] = "1.2.3";
5793
5794     if (0)
5795     {
5796         /* Crashes on win9x */
5797         SetLastError(0xdeadbeef);
5798         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5799          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5800         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5801          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5802     }
5803     SetLastError(0xdeadbeef);
5804     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5805      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5806     ok(!ret && (GetLastError() == E_INVALIDARG ||
5807      GetLastError() == OSS_LIMITED /* Win9x */),
5808      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5809     info.pszObjId = oid1;
5810     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5811      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5812     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5813     if (buf)
5814     {
5815         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5816         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5817         LocalFree(buf);
5818     }
5819     info.Content.pbData = bogusDER;
5820     info.Content.cbData = sizeof(bogusDER);
5821     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5822      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5823     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5824     if (buf)
5825     {
5826         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5827         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5828         LocalFree(buf);
5829     }
5830     info.Content.pbData = (BYTE *)ints[0].encoded;
5831     info.Content.cbData = ints[0].encoded[1] + 2;
5832     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5833      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5834     if (buf)
5835     {
5836         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5837         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5838         LocalFree(buf);
5839     }
5840 }
5841
5842 static const BYTE indefiniteSignedPKCSContent[] = {
5843 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5844 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5845 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5846 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5847 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5848 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5849 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5850 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5851 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5852 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5853 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5854 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5855 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5856 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5857 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5858 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5859 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5860 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5861 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5862 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5863 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5864 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5865 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5866 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5867 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5868 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5869 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5870 0x00,0x00,0x00,0x00,0x00,0x00 };
5871
5872 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5873 {
5874     BOOL ret;
5875     LPBYTE buf = NULL;
5876     DWORD size = 0;
5877     CRYPT_CONTENT_INFO *info;
5878
5879     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5880      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5881      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5882     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5883     if (buf)
5884     {
5885         info = (CRYPT_CONTENT_INFO *)buf;
5886
5887         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5888          info->pszObjId);
5889         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5890          info->Content.cbData);
5891         LocalFree(buf);
5892     }
5893     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5894      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5895      0, NULL, NULL, &size);
5896     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5897     SetLastError(0xdeadbeef);
5898     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5899      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5900      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5901     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5902      * I doubt an app depends on that.
5903      */
5904     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5905      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5906      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5907      GetLastError());
5908     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5909      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5910      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5911     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5912     if (buf)
5913     {
5914         info = (CRYPT_CONTENT_INFO *)buf;
5915
5916         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5917          info->pszObjId);
5918         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5919          "Unexpected size %d\n", info->Content.cbData);
5920         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5921          info->Content.cbData), "Unexpected value\n");
5922         LocalFree(buf);
5923     }
5924     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5925      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5926      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5927     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5928     if (buf)
5929     {
5930         info = (CRYPT_CONTENT_INFO *)buf;
5931
5932         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5933          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5934         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5935          info->Content.cbData);
5936         LocalFree(buf);
5937     }
5938 }
5939
5940 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5941  0x00 };
5942 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5943  0x01 };
5944 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5945  0x02,0x01,0x01 };
5946
5947 static void test_encodePKCSAttribute(DWORD dwEncoding)
5948 {
5949     CRYPT_ATTRIBUTE attr = { 0 };
5950     BOOL ret;
5951     LPBYTE buf = NULL;
5952     DWORD size = 0;
5953     CRYPT_ATTR_BLOB blob;
5954     char oid[] = "1.2.3";
5955
5956     if (0)
5957     {
5958         /* Crashes on win9x */
5959         SetLastError(0xdeadbeef);
5960         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5961          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5962         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5963          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5964     }
5965     SetLastError(0xdeadbeef);
5966     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5967      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5968     ok(!ret && (GetLastError() == E_INVALIDARG ||
5969      GetLastError() == OSS_LIMITED /* Win9x */),
5970      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5971     attr.pszObjId = oid;
5972     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5973      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5974     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5975     if (buf)
5976     {
5977         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5978         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5979         LocalFree(buf);
5980     }
5981     blob.cbData = sizeof(bogusDER);
5982     blob.pbData = bogusDER;
5983     attr.cValue = 1;
5984     attr.rgValue = &blob;
5985     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5986      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5987     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5988     if (buf)
5989     {
5990         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5991         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5992         LocalFree(buf);
5993     }
5994     blob.pbData = (BYTE *)ints[0].encoded;
5995     blob.cbData = ints[0].encoded[1] + 2;
5996     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5997      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5998     if (buf)
5999     {
6000         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6001         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6002         LocalFree(buf);
6003     }
6004 }
6005
6006 static void test_decodePKCSAttribute(DWORD dwEncoding)
6007 {
6008     BOOL ret;
6009     LPBYTE buf = NULL;
6010     DWORD size = 0;
6011     CRYPT_ATTRIBUTE *attr;
6012
6013     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6014      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6015      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6016     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6017     if (buf)
6018     {
6019         attr = (CRYPT_ATTRIBUTE *)buf;
6020
6021         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6022          attr->pszObjId);
6023         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6024         LocalFree(buf);
6025     }
6026     SetLastError(0xdeadbeef);
6027     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6028      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6029      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6030     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6031      * I doubt an app depends on that.
6032      */
6033     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6034      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6035      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6036      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6037      GetLastError());
6038     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6039      intPKCSAttr, sizeof(intPKCSAttr),
6040      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6041     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6042     if (buf)
6043     {
6044         attr = (CRYPT_ATTRIBUTE *)buf;
6045
6046         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6047          attr->pszObjId);
6048         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6049         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6050          "Unexpected size %d\n", attr->rgValue[0].cbData);
6051         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6052          attr->rgValue[0].cbData), "Unexpected value\n");
6053         LocalFree(buf);
6054     }
6055 }
6056
6057 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6058 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6059  0x2a,0x03,0x31,0x00 };
6060 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6061  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6062
6063 static void test_encodePKCSAttributes(DWORD dwEncoding)
6064 {
6065     CRYPT_ATTRIBUTES attributes = { 0 };
6066     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6067     CRYPT_ATTR_BLOB blob;
6068     BOOL ret;
6069     LPBYTE buf = NULL;
6070     DWORD size = 0;
6071     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6072
6073     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6074      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6075     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6076     if (buf)
6077     {
6078         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6079         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6080         LocalFree(buf);
6081     }
6082     attributes.cAttr = 1;
6083     attributes.rgAttr = attr;
6084     SetLastError(0xdeadbeef);
6085     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6086      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6087     ok(!ret && (GetLastError() == E_INVALIDARG ||
6088      GetLastError() == OSS_LIMITED /* Win9x */),
6089      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6090     attr[0].pszObjId = oid1;
6091     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6092      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6093     if (buf)
6094     {
6095         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6096         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6097         LocalFree(buf);
6098     }
6099     attr[1].pszObjId = oid2;
6100     attr[1].cValue = 1;
6101     attr[1].rgValue = &blob;
6102     blob.pbData = (BYTE *)ints[0].encoded;
6103     blob.cbData = ints[0].encoded[1] + 2;
6104     attributes.cAttr = 2;
6105     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6107     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6108     if (buf)
6109     {
6110         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6111         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6112         LocalFree(buf);
6113     }
6114 }
6115
6116 static void test_decodePKCSAttributes(DWORD dwEncoding)
6117 {
6118     BOOL ret;
6119     LPBYTE buf = NULL;
6120     DWORD size = 0;
6121     CRYPT_ATTRIBUTES *attributes;
6122
6123     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6124      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6125      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6126     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6127     if (buf)
6128     {
6129         attributes = (CRYPT_ATTRIBUTES *)buf;
6130         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6131          attributes->cAttr);
6132         LocalFree(buf);
6133     }
6134     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6135      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6136      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6137     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6138     if (buf)
6139     {
6140         attributes = (CRYPT_ATTRIBUTES *)buf;
6141         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6142          attributes->cAttr);
6143         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6144          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6145         ok(attributes->rgAttr[0].cValue == 0,
6146          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6147         LocalFree(buf);
6148     }
6149     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6150      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6151      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6152     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6153     if (buf)
6154     {
6155         attributes = (CRYPT_ATTRIBUTES *)buf;
6156         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6157          attributes->cAttr);
6158         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6159          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6160         ok(attributes->rgAttr[0].cValue == 0,
6161          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6162         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6163          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6164         ok(attributes->rgAttr[1].cValue == 1,
6165          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6166         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6167          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6168         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6169          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6170         LocalFree(buf);
6171     }
6172 }
6173
6174 static const BYTE singleCapability[] = {
6175 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6176 static const BYTE twoCapabilities[] = {
6177 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6178 static const BYTE singleCapabilitywithNULL[] = {
6179 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6180
6181 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6182 {
6183     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6184     BOOL ret;
6185     LPBYTE buf = NULL;
6186     DWORD size = 0;
6187     CRYPT_SMIME_CAPABILITY capability[2];
6188     CRYPT_SMIME_CAPABILITIES capabilities;
6189
6190     /* An empty capabilities is allowed */
6191     capabilities.cCapability = 0;
6192     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6193      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6194     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6195     if (buf)
6196     {
6197         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6198         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6199         LocalFree(buf);
6200     }
6201     /* A non-empty capabilities with an empty capability (lacking an OID) is
6202      * not allowed
6203      */
6204     capability[0].pszObjId = NULL;
6205     capability[0].Parameters.cbData = 0;
6206     capabilities.cCapability = 1;
6207     capabilities.rgCapability = capability;
6208     SetLastError(0xdeadbeef);
6209     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6210      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6211     ok(!ret && (GetLastError() == E_INVALIDARG ||
6212      GetLastError() == OSS_LIMITED /* Win9x */),
6213      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6214     capability[0].pszObjId = oid1;
6215     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6216      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6217     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6218     if (buf)
6219     {
6220         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6221         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6222         LocalFree(buf);
6223     }
6224     capability[1].pszObjId = oid2;
6225     capability[1].Parameters.cbData = 0;
6226     capabilities.cCapability = 2;
6227     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6228      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6229     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6230     if (buf)
6231     {
6232         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6233         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6234         LocalFree(buf);
6235     }
6236 }
6237
6238 static void compareSMimeCapabilities(LPCSTR header,
6239  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6240 {
6241     DWORD i;
6242
6243     ok(got->cCapability == expected->cCapability,
6244      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6245      got->cCapability);
6246     for (i = 0; i < expected->cCapability; i++)
6247     {
6248         ok(!strcmp(expected->rgCapability[i].pszObjId,
6249          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6250          header, i, expected->rgCapability[i].pszObjId,
6251          got->rgCapability[i].pszObjId);
6252         ok(expected->rgCapability[i].Parameters.cbData ==
6253          got->rgCapability[i].Parameters.cbData,
6254          "%s[%d]: expected %d bytes, got %d\n", header, i,
6255          expected->rgCapability[i].Parameters.cbData,
6256          got->rgCapability[i].Parameters.cbData);
6257         if (expected->rgCapability[i].Parameters.cbData)
6258             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6259              got->rgCapability[i].Parameters.pbData,
6260              expected->rgCapability[i].Parameters.cbData),
6261              "%s[%d]: unexpected value\n", header, i);
6262     }
6263 }
6264
6265 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6266 {
6267     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6268     BOOL ret;
6269     DWORD size = 0;
6270     CRYPT_SMIME_CAPABILITY capability[2];
6271     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6272
6273     SetLastError(0xdeadbeef);
6274     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6275      emptySequence, sizeof(emptySequence),
6276      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6277     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6278     if (ret)
6279     {
6280         capabilities.cCapability = 0;
6281         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6282         LocalFree(ptr);
6283     }
6284     SetLastError(0xdeadbeef);
6285     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6286      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6287      &ptr, &size);
6288     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6289     if (ret)
6290     {
6291         capability[0].pszObjId = oid1;
6292         capability[0].Parameters.cbData = 0;
6293         capabilities.cCapability = 1;
6294         capabilities.rgCapability = capability;
6295         compareSMimeCapabilities("single capability", &capabilities, ptr);
6296         LocalFree(ptr);
6297     }
6298     SetLastError(0xdeadbeef);
6299     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6300      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6301      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6302     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6303     if (ret)
6304     {
6305         BYTE NULLparam[] = {0x05, 0x00};
6306         capability[0].pszObjId = oid1;
6307         capability[0].Parameters.cbData = 2;
6308         capability[0].Parameters.pbData = NULLparam;
6309         capabilities.cCapability = 1;
6310         capabilities.rgCapability = capability;
6311         compareSMimeCapabilities("single capability with NULL", &capabilities,
6312          ptr);
6313         LocalFree(ptr);
6314     }
6315     SetLastError(0xdeadbeef);
6316     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6317     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6318     &ptr, &size);
6319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6320     if (ret)
6321     {
6322         capability[0].Parameters.cbData = 0;
6323         capability[1].pszObjId = oid2;
6324         capability[1].Parameters.cbData = 0;
6325         capabilities.cCapability = 2;
6326         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6327         LocalFree(ptr);
6328     }
6329 }
6330
6331 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6332  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6333  0x67 };
6334 static const BYTE minimalPKCSSigner[] = {
6335  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6336  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6337  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6338 static const BYTE PKCSSignerWithSerial[] = {
6339  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6340  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6341  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6342  0x00 };
6343 static const BYTE PKCSSignerWithHashAlgo[] = {
6344  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6345  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6346  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6347  0x00,0x04,0x00 };
6348 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6349  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6350  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6351  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6352  0x06,0x05,0x00,0x04,0x00 };
6353 static const BYTE PKCSSignerWithHash[] = {
6354  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6355  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6356  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6357  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6358  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6359 static const BYTE PKCSSignerWithAuthAttr[] = {
6360 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6361 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6362 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6363 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6364 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6365 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6366 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6367
6368 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6369 {
6370     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6371     BOOL ret;
6372     LPBYTE buf = NULL;
6373     DWORD size = 0;
6374     CMSG_SIGNER_INFO info = { 0 };
6375     char oid_common_name[] = szOID_COMMON_NAME;
6376     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6377      (LPBYTE)encodedCommonName };
6378     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6379
6380     SetLastError(0xdeadbeef);
6381     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6382      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6383     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6384     {
6385         skip("no PKCS7_SIGNER_INFO encode support\n");
6386         return;
6387     }
6388     ok(!ret && (GetLastError() == E_INVALIDARG ||
6389      GetLastError() == OSS_LIMITED /* Win9x */),
6390      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6391     /* To be encoded, a signer must have an issuer at least, and the encoding
6392      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6393      * see decoding tests.)
6394      */
6395     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6396     info.Issuer.pbData = encodedCommonNameNoNull;
6397     SetLastError(0xdeadbeef);
6398     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6400     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6401         ok(!ret && GetLastError() == E_INVALIDARG,
6402          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6403     else
6404     {
6405         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6406          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6407         if (buf)
6408         {
6409             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6410             if (size == sizeof(minimalPKCSSigner))
6411                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6412             else
6413                 ok(0, "Unexpected value\n");
6414             LocalFree(buf);
6415         }
6416     }
6417     info.SerialNumber.cbData = sizeof(serialNum);
6418     info.SerialNumber.pbData = (BYTE *)serialNum;
6419     SetLastError(0xdeadbeef);
6420     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6421      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6422     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6423         ok(!ret && GetLastError() == E_INVALIDARG,
6424          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6425     else
6426     {
6427         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6428          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6429         if (buf)
6430         {
6431             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6432              size);
6433             if (size == sizeof(PKCSSignerWithSerial))
6434                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6435                  "Unexpected value\n");
6436             else
6437                 ok(0, "Unexpected value\n");
6438             LocalFree(buf);
6439         }
6440     }
6441     info.HashAlgorithm.pszObjId = oid1;
6442     SetLastError(0xdeadbeef);
6443     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6444      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6445     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6446         ok(!ret && GetLastError() == E_INVALIDARG,
6447          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6448     else
6449     {
6450         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6451          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6452         if (buf)
6453         {
6454             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6455              size);
6456             if (size == sizeof(PKCSSignerWithHashAlgo))
6457                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6458                  "Unexpected value\n");
6459             else
6460                 ok(0, "Unexpected value\n");
6461             LocalFree(buf);
6462         }
6463     }
6464     info.HashEncryptionAlgorithm.pszObjId = oid2;
6465     SetLastError(0xdeadbeef);
6466     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6467      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6468     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6469         ok(!ret && GetLastError() == E_INVALIDARG,
6470          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6471     else
6472     {
6473         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6474         if (buf)
6475         {
6476             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6477              "Unexpected size %d\n", size);
6478             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6479                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6480                  "Unexpected value\n");
6481             else
6482                 ok(0, "Unexpected value\n");
6483             LocalFree(buf);
6484         }
6485     }
6486     info.EncryptedHash.cbData = sizeof(hash);
6487     info.EncryptedHash.pbData = (BYTE *)hash;
6488     SetLastError(0xdeadbeef);
6489     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6490      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6491     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6492         ok(!ret && GetLastError() == E_INVALIDARG,
6493          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6494     else
6495     {
6496         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6497         if (buf)
6498         {
6499             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6500              size);
6501             if (size == sizeof(PKCSSignerWithHash))
6502                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6503                  "Unexpected value\n");
6504             else
6505                 ok(0, "Unexpected value\n");
6506             LocalFree(buf);
6507         }
6508     }
6509     info.AuthAttrs.cAttr = 1;
6510     info.AuthAttrs.rgAttr = &attr;
6511     SetLastError(0xdeadbeef);
6512     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6513      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6514     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6515         ok(!ret && GetLastError() == E_INVALIDARG,
6516          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6517     else
6518     {
6519         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6520         if (buf)
6521         {
6522             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6523              size);
6524             if (size == sizeof(PKCSSignerWithAuthAttr))
6525                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6526                  "Unexpected value\n");
6527             else
6528                 ok(0, "Unexpected value\n");
6529             LocalFree(buf);
6530         }
6531     }
6532 }
6533
6534 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6535 {
6536     BOOL ret;
6537     LPBYTE buf = NULL;
6538     DWORD size = 0;
6539     CMSG_SIGNER_INFO *info;
6540
6541     /* A PKCS signer can't be decoded without a serial number. */
6542     SetLastError(0xdeadbeef);
6543     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6544      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6545      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6546     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6547      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6548      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6549      GetLastError());
6550     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6551      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6552      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6553     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6554      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6555     if (buf)
6556     {
6557         info = (CMSG_SIGNER_INFO *)buf;
6558         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6559          info->dwVersion);
6560         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6561          "Unexpected size %d\n", info->Issuer.cbData);
6562         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6563          info->Issuer.cbData), "Unexpected value\n");
6564         ok(info->SerialNumber.cbData == sizeof(serialNum),
6565          "Unexpected size %d\n", info->SerialNumber.cbData);
6566         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6567          "Unexpected value\n");
6568         LocalFree(buf);
6569     }
6570     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6571      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6572      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6573     if (buf)
6574     {
6575         info = (CMSG_SIGNER_INFO *)buf;
6576         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6577          info->dwVersion);
6578         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6579          "Unexpected size %d\n", info->Issuer.cbData);
6580         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6581          info->Issuer.cbData), "Unexpected value\n");
6582         ok(info->SerialNumber.cbData == sizeof(serialNum),
6583          "Unexpected size %d\n", info->SerialNumber.cbData);
6584         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6585          "Unexpected value\n");
6586         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6587          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6588         LocalFree(buf);
6589     }
6590     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6591      PKCSSignerWithHashAndEncryptionAlgo,
6592      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6593      NULL, &buf, &size);
6594     if (buf)
6595     {
6596         info = (CMSG_SIGNER_INFO *)buf;
6597         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6598          info->dwVersion);
6599         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6600          "Unexpected size %d\n", info->Issuer.cbData);
6601         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6602          info->Issuer.cbData), "Unexpected value\n");
6603         ok(info->SerialNumber.cbData == sizeof(serialNum),
6604          "Unexpected size %d\n", info->SerialNumber.cbData);
6605         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6606          "Unexpected value\n");
6607         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6608          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6609         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6610          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6611         LocalFree(buf);
6612     }
6613     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6614      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6615      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6616     if (buf)
6617     {
6618         info = (CMSG_SIGNER_INFO *)buf;
6619         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6620          info->dwVersion);
6621         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6622          "Unexpected size %d\n", info->Issuer.cbData);
6623         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6624          info->Issuer.cbData), "Unexpected value\n");
6625         ok(info->SerialNumber.cbData == sizeof(serialNum),
6626          "Unexpected size %d\n", info->SerialNumber.cbData);
6627         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6628          "Unexpected value\n");
6629         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6630          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6631         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6632          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6633         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6634          info->EncryptedHash.cbData);
6635         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6636          "Unexpected value\n");
6637         LocalFree(buf);
6638     }
6639     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6640      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6641      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6642     if (buf)
6643     {
6644         info = (CMSG_SIGNER_INFO *)buf;
6645         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6646          info->AuthAttrs.cAttr);
6647         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6648          "Expected %s, got %s\n", szOID_COMMON_NAME,
6649          info->AuthAttrs.rgAttr[0].pszObjId);
6650         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6651          info->AuthAttrs.rgAttr[0].cValue);
6652         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6653          sizeof(encodedCommonName), "Unexpected size %d\n",
6654          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6655         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6656          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6657         LocalFree(buf);
6658     }
6659 }
6660
6661 static const BYTE CMSSignerWithKeyId[] = {
6662 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6663 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6664
6665 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6666 {
6667     BOOL ret;
6668     LPBYTE buf = NULL;
6669     DWORD size = 0;
6670     CMSG_CMS_SIGNER_INFO info = { 0 };
6671     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6672
6673     SetLastError(0xdeadbeef);
6674     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6675      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6676     ok(!ret, "Expected failure, got %d\n", ret);
6677     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6678     {
6679         skip("no CMS_SIGNER_INFO encode support\n");
6680         return;
6681     }
6682     ok(GetLastError() == E_INVALIDARG,
6683        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6684     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6685     SetLastError(0xdeadbeef);
6686     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6687      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6688     ok(!ret, "Expected failure, got %d\n", ret);
6689     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6690     {
6691         skip("no CMS_SIGNER_INFO encode support\n");
6692         return;
6693     }
6694     ok(GetLastError() == E_INVALIDARG,
6695        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6696     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6697      * be a key id or a issuer serial number with at least the issuer set, and
6698      * the encoding must include PKCS_7_ASN_ENCODING.
6699      * (That isn't enough to be decoded, see decoding tests.)
6700      */
6701     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6702      sizeof(encodedCommonNameNoNull);
6703     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6704     SetLastError(0xdeadbeef);
6705     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6706      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6707     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6708         ok(!ret && GetLastError() == E_INVALIDARG,
6709          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6710     else
6711     {
6712         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6713         if (buf)
6714         {
6715             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6716             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6717             LocalFree(buf);
6718         }
6719     }
6720     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6721     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6722     SetLastError(0xdeadbeef);
6723     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6724      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6725     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6726         ok(!ret && GetLastError() == E_INVALIDARG,
6727          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6728     else
6729     {
6730         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6731         if (buf)
6732         {
6733             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6734              size);
6735             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6736             LocalFree(buf);
6737         }
6738     }
6739     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6740     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6741     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6742     SetLastError(0xdeadbeef);
6743     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6744      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6745     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6746         ok(!ret && GetLastError() == E_INVALIDARG,
6747          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6748     else
6749     {
6750         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6751         if (buf)
6752         {
6753             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6754              size);
6755             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6756             LocalFree(buf);
6757         }
6758     }
6759     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6760      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6761      * (see RFC 3852, section 5.3.)
6762      */
6763     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6764     U(info.SignerId).HashId.cbData = sizeof(hash);
6765     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6766     SetLastError(0xdeadbeef);
6767     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6768      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6769     ok(!ret && GetLastError() == E_INVALIDARG,
6770      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6771     /* Now with a hash algo */
6772     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6773     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6774      sizeof(encodedCommonNameNoNull);
6775     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6776     info.HashAlgorithm.pszObjId = oid1;
6777     SetLastError(0xdeadbeef);
6778     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6779      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6780     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6781         ok(!ret && GetLastError() == E_INVALIDARG,
6782          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6783     else
6784     {
6785         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6786         if (buf)
6787         {
6788             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6789              size);
6790             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6791              "Unexpected value\n");
6792             LocalFree(buf);
6793         }
6794     }
6795     info.HashEncryptionAlgorithm.pszObjId = oid2;
6796     SetLastError(0xdeadbeef);
6797     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6798      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6799     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6800         ok(!ret && GetLastError() == E_INVALIDARG,
6801          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6802     else
6803     {
6804         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6805         if (buf)
6806         {
6807             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6808              "Unexpected size %d\n", size);
6809             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6810              "Unexpected value\n");
6811             LocalFree(buf);
6812         }
6813     }
6814     info.EncryptedHash.cbData = sizeof(hash);
6815     info.EncryptedHash.pbData = (BYTE *)hash;
6816     SetLastError(0xdeadbeef);
6817     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6818      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6819     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6820         ok(!ret && GetLastError() == E_INVALIDARG,
6821          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6822     else
6823     {
6824         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6825         if (buf)
6826         {
6827             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6828              size);
6829             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6830             LocalFree(buf);
6831         }
6832     }
6833 }
6834
6835 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6836 {
6837     BOOL ret;
6838     LPBYTE buf = NULL;
6839     DWORD size = 0;
6840     CMSG_CMS_SIGNER_INFO *info;
6841     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6842
6843     /* A CMS signer can't be decoded without a serial number. */
6844     SetLastError(0xdeadbeef);
6845     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6846      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6847      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6848     ok(!ret, "expected failure\n");
6849     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6850     {
6851         skip("no CMS_SIGNER_INFO decode support\n");
6852         return;
6853     }
6854     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6855      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6856     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6857      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6858      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6859     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6860     if (buf)
6861     {
6862         info = (CMSG_CMS_SIGNER_INFO *)buf;
6863         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6864          info->dwVersion);
6865         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6866          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6867          info->SignerId.dwIdChoice);
6868         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6869          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6870          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6871         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6872          encodedCommonNameNoNull,
6873          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6874          "Unexpected value\n");
6875         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6876          sizeof(serialNum), "Unexpected size %d\n",
6877          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6878         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6879          serialNum, sizeof(serialNum)), "Unexpected value\n");
6880         LocalFree(buf);
6881     }
6882     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6883      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6884      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6885     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6886     if (buf)
6887     {
6888         info = (CMSG_CMS_SIGNER_INFO *)buf;
6889         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6890          info->dwVersion);
6891         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6892          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6893          info->SignerId.dwIdChoice);
6894         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6895          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6896          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6897         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6898          encodedCommonNameNoNull,
6899          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6900          "Unexpected value\n");
6901         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6902          sizeof(serialNum), "Unexpected size %d\n",
6903          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6904         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6905          serialNum, sizeof(serialNum)), "Unexpected value\n");
6906         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6907          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6908         LocalFree(buf);
6909     }
6910     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6911      PKCSSignerWithHashAndEncryptionAlgo,
6912      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6913      NULL, &buf, &size);
6914     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6915     if (buf)
6916     {
6917         info = (CMSG_CMS_SIGNER_INFO *)buf;
6918         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6919          info->dwVersion);
6920         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6921          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6922          info->SignerId.dwIdChoice);
6923         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6924          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6925          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6926         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6927          encodedCommonNameNoNull,
6928          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6929          "Unexpected value\n");
6930         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6931          sizeof(serialNum), "Unexpected size %d\n",
6932          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6933         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6934          serialNum, sizeof(serialNum)), "Unexpected value\n");
6935         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6936          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6937         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6938          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6939         LocalFree(buf);
6940     }
6941     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6942      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6943      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6944     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6945     if (buf)
6946     {
6947         info = (CMSG_CMS_SIGNER_INFO *)buf;
6948         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6949          info->dwVersion);
6950         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6951          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6952          info->SignerId.dwIdChoice);
6953         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6954          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6955          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6956         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6957          encodedCommonNameNoNull,
6958          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6959          "Unexpected value\n");
6960         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6961          sizeof(serialNum), "Unexpected size %d\n",
6962          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6963         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6964          serialNum, sizeof(serialNum)), "Unexpected value\n");
6965         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6966          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6967         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6968          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6969         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6970          info->EncryptedHash.cbData);
6971         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6972          "Unexpected value\n");
6973         LocalFree(buf);
6974     }
6975     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6976      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6977      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6978     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6979     if (buf)
6980     {
6981         info = (CMSG_CMS_SIGNER_INFO *)buf;
6982         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6983          info->dwVersion);
6984         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6985          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6986          info->SignerId.dwIdChoice);
6987         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6988          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6989         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6990          "Unexpected value\n");
6991         LocalFree(buf);
6992     }
6993 }
6994
6995 static BYTE emptyDNSPermittedConstraints[] = {
6996 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6997 static BYTE emptyDNSExcludedConstraints[] = {
6998 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6999 static BYTE DNSExcludedConstraints[] = {
7000 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7001 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7002 static BYTE permittedAndExcludedConstraints[] = {
7003 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7004 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7005 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7006 static BYTE permittedAndExcludedWithMinConstraints[] = {
7007 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7008 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7009 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7010 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7011 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7012 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7013 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7014
7015 static void test_encodeNameConstraints(DWORD dwEncoding)
7016 {
7017     BOOL ret;
7018     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7019     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7020     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7021     LPBYTE buf;
7022     DWORD size;
7023
7024     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7025      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7026     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7027     {
7028         skip("no X509_NAME_CONSTRAINTS encode support\n");
7029         return;
7030     }
7031     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7032     if (ret)
7033     {
7034         ok(size == sizeof(emptySequence), "Unexpected size\n");
7035         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7036         LocalFree(buf);
7037     }
7038     constraints.cPermittedSubtree = 1;
7039     constraints.rgPermittedSubtree = &permitted;
7040     SetLastError(0xdeadbeef);
7041     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7042      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7043     ok(!ret && GetLastError() == E_INVALIDARG,
7044      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7045     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7046     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7047      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7048     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7049     if (ret)
7050     {
7051         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7052         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7053          "Unexpected value\n");
7054         LocalFree(buf);
7055     }
7056     constraints.cPermittedSubtree = 0;
7057     constraints.cExcludedSubtree = 1;
7058     constraints.rgExcludedSubtree = &excluded;
7059     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7060     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7061      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7062     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7063     if (ret)
7064     {
7065         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7066         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7067          "Unexpected value\n");
7068         LocalFree(buf);
7069     }
7070     U(excluded.Base).pwszURL = (LPWSTR)url;
7071     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7072      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7073     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7074     if (ret)
7075     {
7076         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7077         ok(!memcmp(buf, DNSExcludedConstraints, size),
7078          "Unexpected value\n");
7079         LocalFree(buf);
7080     }
7081     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7082     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7083     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7084     constraints.cPermittedSubtree = 1;
7085     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7086      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7087     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7088     if (ret)
7089     {
7090         ok(size == sizeof(permittedAndExcludedConstraints),
7091          "Unexpected size\n");
7092         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7093          "Unexpected value\n");
7094         LocalFree(buf);
7095     }
7096     permitted.dwMinimum = 5;
7097     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7098      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7099     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7100     if (ret)
7101     {
7102         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7103          "Unexpected size\n");
7104         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7105          "Unexpected value\n");
7106         LocalFree(buf);
7107     }
7108     permitted.fMaximum = TRUE;
7109     permitted.dwMaximum = 3;
7110     SetLastError(0xdeadbeef);
7111     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7112      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7113     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7114     if (ret)
7115     {
7116         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7117          "Unexpected size\n");
7118         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7119          "Unexpected value\n");
7120         LocalFree(buf);
7121     }
7122 }
7123
7124 struct EncodedNameConstraints
7125 {
7126     CRYPT_DATA_BLOB            encoded;
7127     CERT_NAME_CONSTRAINTS_INFO constraints;
7128 };
7129
7130 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7131  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7132 static CERT_GENERAL_SUBTREE DNSSubtree = {
7133  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7134 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7135  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7136 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7137  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7138 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7139  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7140
7141 struct EncodedNameConstraints encodedNameConstraints[] = {
7142  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7143  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7144    { 1, &emptyDNSSubtree, 0, NULL } },
7145  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7146    { 0, NULL, 1, &emptyDNSSubtree } },
7147  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7148    { 0, NULL, 1, &DNSSubtree } },
7149  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7150    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7151  { { sizeof(permittedAndExcludedWithMinConstraints),
7152      permittedAndExcludedWithMinConstraints },
7153    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7154  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7155      permittedAndExcludedWithMinMaxConstraints },
7156    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7157 };
7158
7159 static void test_decodeNameConstraints(DWORD dwEncoding)
7160 {
7161     BOOL ret;
7162     DWORD i;
7163     CERT_NAME_CONSTRAINTS_INFO *constraints;
7164
7165     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7166     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7167     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7168     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7169     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7170     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7171     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7172     for (i = 0;
7173      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7174      i++)
7175     {
7176         DWORD size;
7177
7178         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7179          encodedNameConstraints[i].encoded.pbData,
7180          encodedNameConstraints[i].encoded.cbData,
7181          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7182         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7183         {
7184             skip("no X509_NAME_CONSTRAINTS decode support\n");
7185             return;
7186         }
7187         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7188         if (ret)
7189         {
7190             DWORD j;
7191
7192             if (constraints->cPermittedSubtree !=
7193              encodedNameConstraints[i].constraints.cPermittedSubtree)
7194                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7195                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7196                  constraints->cPermittedSubtree);
7197             if (constraints->cPermittedSubtree ==
7198              encodedNameConstraints[i].constraints.cPermittedSubtree)
7199             {
7200                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7201                 {
7202                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7203                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7204                 }
7205             }
7206             if (constraints->cExcludedSubtree !=
7207              encodedNameConstraints[i].constraints.cExcludedSubtree)
7208                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7209                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7210                  constraints->cExcludedSubtree);
7211             if (constraints->cExcludedSubtree ==
7212              encodedNameConstraints[i].constraints.cExcludedSubtree)
7213             {
7214                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7215                 {
7216                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7217                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7218                 }
7219             }
7220             LocalFree(constraints);
7221         }
7222     }
7223 }
7224
7225 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7226  'n','o','t','i','c','e',0 };
7227 static const BYTE noticeWithDisplayText[] = {
7228  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7229  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7230  0x00,0x69,0x00,0x63,0x00,0x65
7231 };
7232 static char org[] = "Wine";
7233 static int noticeNumbers[] = { 2,3 };
7234 static BYTE noticeWithReference[] = {
7235  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7236  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7237  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7238  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7239 };
7240
7241 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7242 {
7243     BOOL ret;
7244     LPBYTE buf;
7245     DWORD size;
7246     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7247     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7248
7249     memset(&notice, 0, sizeof(notice));
7250     ret = pCryptEncodeObjectEx(dwEncoding,
7251      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7252      NULL, &buf, &size);
7253     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7254     {
7255         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7256         return;
7257     }
7258     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7259     if (ret)
7260     {
7261         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7262         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7263         LocalFree(buf);
7264     }
7265     notice.pszDisplayText = noticeText;
7266     ret = pCryptEncodeObjectEx(dwEncoding,
7267      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7268      NULL, &buf, &size);
7269     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7270     if (ret)
7271     {
7272         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7273         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7274         LocalFree(buf);
7275     }
7276     reference.pszOrganization = org;
7277     reference.cNoticeNumbers = 2;
7278     reference.rgNoticeNumbers = noticeNumbers;
7279     notice.pNoticeReference = &reference;
7280     ret = pCryptEncodeObjectEx(dwEncoding,
7281      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7282      NULL, &buf, &size);
7283     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7284     if (ret)
7285     {
7286         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7287         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7288         LocalFree(buf);
7289     }
7290 }
7291
7292 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7293 {
7294     BOOL ret;
7295     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7296     DWORD size;
7297
7298     ret = pCryptDecodeObjectEx(dwEncoding,
7299      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7300      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7301      &notice, &size);
7302     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7303     {
7304         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7305         return;
7306     }
7307     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7308     if (ret)
7309     {
7310         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7311         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7312         LocalFree(notice);
7313     }
7314     ret = pCryptDecodeObjectEx(dwEncoding,
7315      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7316      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7317      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7318     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7319     if (ret)
7320     {
7321         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7322          "unexpected display text\n");
7323         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7324         LocalFree(notice);
7325     }
7326     ret = pCryptDecodeObjectEx(dwEncoding,
7327      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7328      noticeWithReference, sizeof(noticeWithReference),
7329      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7330     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7331     if (ret)
7332     {
7333         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7334          "unexpected display text\n");
7335         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7336         if (notice->pNoticeReference)
7337         {
7338             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7339              "unexpected organization %s\n",
7340              notice->pNoticeReference->pszOrganization);
7341             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7342              "expected 2 notice numbers, got %d\n",
7343              notice->pNoticeReference->cNoticeNumbers);
7344             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7345              "unexpected notice number %d\n",
7346              notice->pNoticeReference->rgNoticeNumbers[0]);
7347             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7348              "unexpected notice number %d\n",
7349              notice->pNoticeReference->rgNoticeNumbers[1]);
7350         }
7351         LocalFree(notice);
7352     }
7353 }
7354
7355 static char oid_any_policy[] = "2.5.29.32.0";
7356 static const BYTE policiesWithAnyPolicy[] = {
7357  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7358 };
7359 static char oid1[] = "1.2.3";
7360 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7361 static const BYTE twoPolicies[] = {
7362  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7363  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7364  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7365  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7366  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7367  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7368 };
7369
7370 static void test_encodeCertPolicies(DWORD dwEncoding)
7371 {
7372     BOOL ret;
7373     CERT_POLICIES_INFO info;
7374     CERT_POLICY_INFO policy[2];
7375     CERT_POLICY_QUALIFIER_INFO qualifier;
7376     LPBYTE buf;
7377     DWORD size;
7378
7379     memset(&info, 0, sizeof(info));
7380     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7381      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7382     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7383     if (ret)
7384     {
7385         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7386         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7387         LocalFree(buf);
7388     }
7389     memset(policy, 0, sizeof(policy));
7390     info.cPolicyInfo = 1;
7391     info.rgPolicyInfo = policy;
7392     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7393      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7394     ok(!ret && (GetLastError() == E_INVALIDARG ||
7395      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7396      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7397     policy[0].pszPolicyIdentifier = oid_any_policy;
7398     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7400     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7401     if (ret)
7402     {
7403         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7404         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7405         LocalFree(buf);
7406     }
7407     policy[1].pszPolicyIdentifier = oid1;
7408     memset(&qualifier, 0, sizeof(qualifier));
7409     qualifier.pszPolicyQualifierId = oid_user_notice;
7410     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7411     qualifier.Qualifier.pbData = noticeWithReference;
7412     policy[1].cPolicyQualifier = 1;
7413     policy[1].rgPolicyQualifier = &qualifier;
7414     info.cPolicyInfo = 2;
7415     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7416      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7417     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7418     if (ret)
7419     {
7420         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7421         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7422         LocalFree(buf);
7423     }
7424 }
7425
7426 static void test_decodeCertPolicies(DWORD dwEncoding)
7427 {
7428     BOOL ret;
7429     CERT_POLICIES_INFO *info;
7430     DWORD size;
7431
7432     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7433      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7434      &info, &size);
7435     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7436     if (ret)
7437     {
7438         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7439          info->cPolicyInfo);
7440         LocalFree(info);
7441     }
7442     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7443      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7444      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7445     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7446     if (ret)
7447     {
7448         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7449          info->cPolicyInfo);
7450         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7451          "unexpected policy id %s\n",
7452          info->rgPolicyInfo[0].pszPolicyIdentifier);
7453         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7454          "unexpected policy qualifier count %d\n",
7455          info->rgPolicyInfo[0].cPolicyQualifier);
7456         LocalFree(info);
7457     }
7458     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7459      twoPolicies, sizeof(twoPolicies),
7460      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7461     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7462     if (ret)
7463     {
7464         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7465          info->cPolicyInfo);
7466         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7467          "unexpected policy id %s\n",
7468          info->rgPolicyInfo[0].pszPolicyIdentifier);
7469         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7470          "unexpected policy qualifier count %d\n",
7471          info->rgPolicyInfo[0].cPolicyQualifier);
7472         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7473          "unexpected policy id %s\n",
7474          info->rgPolicyInfo[1].pszPolicyIdentifier);
7475         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7476          "unexpected policy qualifier count %d\n",
7477          info->rgPolicyInfo[1].cPolicyQualifier);
7478         ok(!strcmp(
7479          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7480          oid_user_notice), "unexpected policy qualifier id %s\n",
7481          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7482         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7483          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7484          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7485         ok(!memcmp(
7486          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7487          noticeWithReference, sizeof(noticeWithReference)),
7488          "unexpected qualifier value\n");
7489         LocalFree(info);
7490     }
7491 }
7492
7493 static const BYTE policyMappingWithOneMapping[] = {
7494 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7495 static const BYTE policyMappingWithTwoMappings[] = {
7496 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7497 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7498 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7499  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7500
7501 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7502 {
7503     static char oid2[] = "2.3.4";
7504     static char oid3[] = "1.3.4";
7505     static char oid4[] = "2.5.6";
7506     BOOL ret;
7507     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7508     CERT_POLICY_MAPPING mapping[2];
7509     LPBYTE buf;
7510     DWORD size, i;
7511
7512     /* Each of the mapping OIDs is equivalent, so check with all of them */
7513     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7514     {
7515         memset(&info, 0, sizeof(info));
7516         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7517          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7518         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7519          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7520         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7521         {
7522             win_skip("no policy mappings support\n");
7523             return;
7524         }
7525         if (ret)
7526         {
7527             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7528             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7529              "unexpected value\n");
7530             LocalFree(buf);
7531         }
7532         mapping[0].pszIssuerDomainPolicy = NULL;
7533         mapping[0].pszSubjectDomainPolicy = NULL;
7534         info.cPolicyMapping = 1;
7535         info.rgPolicyMapping = mapping;
7536         SetLastError(0xdeadbeef);
7537         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7538          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7539         ok(!ret && GetLastError() == E_INVALIDARG,
7540          "expected E_INVALIDARG, got %08x\n", GetLastError());
7541         mapping[0].pszIssuerDomainPolicy = oid1;
7542         mapping[0].pszSubjectDomainPolicy = oid2;
7543         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7544          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7545         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7546         if (ret)
7547         {
7548             ok(size == sizeof(policyMappingWithOneMapping),
7549              "unexpected size %d\n", size);
7550             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7551              "unexpected value\n");
7552             LocalFree(buf);
7553         }
7554         mapping[1].pszIssuerDomainPolicy = oid3;
7555         mapping[1].pszSubjectDomainPolicy = oid4;
7556         info.cPolicyMapping = 2;
7557         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7558          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7559         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7560         if (ret)
7561         {
7562             ok(size == sizeof(policyMappingWithTwoMappings),
7563              "unexpected size %d\n", size);
7564             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7565              "unexpected value\n");
7566             LocalFree(buf);
7567         }
7568     }
7569 }
7570
7571 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7572 {
7573     DWORD size, i;
7574     CERT_POLICY_MAPPINGS_INFO *info;
7575     BOOL ret;
7576
7577     /* Each of the mapping OIDs is equivalent, so check with all of them */
7578     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7579     {
7580         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7581          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7582          &info, &size);
7583         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7584          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7585         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7586         {
7587             win_skip("no policy mappings support\n");
7588             return;
7589         }
7590         if (ret)
7591         {
7592             ok(info->cPolicyMapping == 0,
7593              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7594             LocalFree(info);
7595         }
7596         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7597          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7598          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7599         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7600         if (ret)
7601         {
7602             ok(info->cPolicyMapping == 1,
7603              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7604             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7605              "unexpected issuer policy %s\n",
7606              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7607             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7608              "2.3.4"), "unexpected subject policy %s\n",
7609              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7610             LocalFree(info);
7611         }
7612         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7613          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7614          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7615         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7616         if (ret)
7617         {
7618             ok(info->cPolicyMapping == 2,
7619              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7620             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7621              "unexpected issuer policy %s\n",
7622              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7623             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7624              "2.3.4"), "unexpected subject policy %s\n",
7625              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7626             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7627              "unexpected issuer policy %s\n",
7628              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7629             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7630              "2.5.6"), "unexpected subject policy %s\n",
7631              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7632             LocalFree(info);
7633         }
7634     }
7635 }
7636
7637 static const BYTE policyConstraintsWithRequireExplicit[] = {
7638 0x30,0x03,0x80,0x01,0x00 };
7639 static const BYTE policyConstraintsWithInhibitMapping[] = {
7640 0x30,0x03,0x81,0x01,0x01 };
7641 static const BYTE policyConstraintsWithBoth[] = {
7642 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7643
7644 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7645 {
7646     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7647     LPBYTE buf;
7648     DWORD size;
7649     BOOL ret;
7650
7651     /* Even though RFC 5280 explicitly states CAs must not issue empty
7652      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7653      */
7654     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7655      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7656     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7657      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7658     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7659     {
7660         win_skip("no policy constraints support\n");
7661         return;
7662     }
7663     if (ret)
7664     {
7665         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7666         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7667          "unexpected value\n");
7668         LocalFree(buf);
7669     }
7670     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7671      * is not, then a skip of 0 is encoded.
7672      */
7673     info.fRequireExplicitPolicy = TRUE;
7674     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7675      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7676     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7677     if (ret)
7678     {
7679         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7680          "unexpected size %d\n", size);
7681         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7682          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7683         LocalFree(buf);
7684     }
7685     /* With inhibit policy mapping */
7686     info.fRequireExplicitPolicy = FALSE;
7687     info.dwRequireExplicitPolicySkipCerts = 0;
7688     info.fInhibitPolicyMapping = TRUE;
7689     info.dwInhibitPolicyMappingSkipCerts = 1;
7690     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7691      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7692     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7693     if (ret)
7694     {
7695         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7696          "unexpected size %d\n", size);
7697         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7698          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7699         LocalFree(buf);
7700     }
7701     /* And with both */
7702     info.fRequireExplicitPolicy = TRUE;
7703     info.dwRequireExplicitPolicySkipCerts = 1;
7704     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7705      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7706     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7707     if (ret)
7708     {
7709         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7710          size);
7711         ok(!memcmp(buf, policyConstraintsWithBoth,
7712          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7713         LocalFree(buf);
7714     }
7715 }
7716
7717 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7718 {
7719     CERT_POLICY_CONSTRAINTS_INFO *info;
7720     DWORD size;
7721     BOOL ret;
7722
7723     /* Again, even though CAs must not issue such constraints, they can be
7724      * decoded.
7725      */
7726     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7727      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7728      &info, &size);
7729     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7730      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7731     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7732     {
7733         win_skip("no policy mappings support\n");
7734         return;
7735     }
7736     if (ret)
7737     {
7738         ok(!info->fRequireExplicitPolicy,
7739          "expected require explicit = FALSE\n");
7740         ok(!info->fInhibitPolicyMapping,
7741          "expected implicit mapping = FALSE\n");
7742         LocalFree(info);
7743     }
7744     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7745      policyConstraintsWithRequireExplicit,
7746      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7747      NULL, &info, &size);
7748     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7749     if (ret)
7750     {
7751         ok(info->fRequireExplicitPolicy,
7752          "expected require explicit = TRUE\n");
7753         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7754          info->dwRequireExplicitPolicySkipCerts);
7755         ok(!info->fInhibitPolicyMapping,
7756          "expected implicit mapping = FALSE\n");
7757         LocalFree(info);
7758     }
7759     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7760      policyConstraintsWithInhibitMapping,
7761      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7762      NULL, &info, &size);
7763     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7764     if (ret)
7765     {
7766         ok(!info->fRequireExplicitPolicy,
7767          "expected require explicit = FALSE\n");
7768         ok(info->fInhibitPolicyMapping,
7769          "expected implicit mapping = TRUE\n");
7770         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7771          info->dwInhibitPolicyMappingSkipCerts);
7772         LocalFree(info);
7773     }
7774     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7775      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7776      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7777     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7778     if (ret)
7779     {
7780         ok(info->fRequireExplicitPolicy,
7781          "expected require explicit = TRUE\n");
7782         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7783          info->dwRequireExplicitPolicySkipCerts);
7784         ok(info->fInhibitPolicyMapping,
7785          "expected implicit mapping = TRUE\n");
7786         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7787          info->dwInhibitPolicyMappingSkipCerts);
7788         LocalFree(info);
7789     }
7790 }
7791
7792 /* Free *pInfo with HeapFree */
7793 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7794 {
7795     BOOL ret;
7796     DWORD size = 0;
7797     HCRYPTKEY key;
7798
7799     /* This crashes
7800     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7801      */
7802     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7803     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7804      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7805     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7806      &size);
7807     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7808      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7809     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7810      NULL, &size);
7811     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7812      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7813     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7814      0, NULL, NULL, &size);
7815     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7816      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7817     /* Test with no key */
7818     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7819      0, NULL, NULL, &size);
7820     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7821      GetLastError());
7822     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7823     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7824     if (ret)
7825     {
7826         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7827          NULL, 0, NULL, NULL, &size);
7828         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7829         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7830         if (*pInfo)
7831         {
7832             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7833              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7834             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7835              GetLastError());
7836             if (ret)
7837             {
7838                 /* By default (we passed NULL as the OID) the OID is
7839                  * szOID_RSA_RSA.
7840                  */
7841                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7842                  "Expected %s, got %s\n", szOID_RSA_RSA,
7843                  (*pInfo)->Algorithm.pszObjId);
7844             }
7845         }
7846     }
7847     CryptDestroyKey(key);
7848 }
7849
7850 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7851  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7852  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7853  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7854  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7855  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7856  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7857  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7858  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7859  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7860  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7861  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7862  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7863  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7864  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7865  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7866  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7867  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7868  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7869  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7870  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7871  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7872  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7873  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7874  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7875
7876 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7877 {
7878     BOOL ret;
7879     HCRYPTKEY key;
7880     PCCERT_CONTEXT context;
7881     DWORD dwSize;
7882     ALG_ID ai;
7883
7884     /* These crash
7885     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7886     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7887     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7888     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7889      NULL);
7890      */
7891     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7892     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7893      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7894     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7895     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7896      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7897     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7898      &key);
7899     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7900      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7901
7902     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7903     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7904      &key);
7905     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7906
7907     dwSize = sizeof(ai);
7908     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7909     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7910     if(ret)
7911     {
7912       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7913       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7914     }
7915
7916     CryptDestroyKey(key);
7917
7918     /* Repeat with forced algorithm */
7919     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7920      &key);
7921     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7922
7923     dwSize = sizeof(ai);
7924     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7925     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7926     if(ret)
7927     {
7928       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7929       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7930     }
7931
7932     CryptDestroyKey(key);
7933
7934     /* Test importing a public key from a certificate context */
7935     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7936      sizeof(expiredCert));
7937     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7938      GetLastError());
7939     if (context)
7940     {
7941         ok(!strcmp(szOID_RSA_RSA,
7942          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7943          "Expected %s, got %s\n", szOID_RSA_RSA,
7944          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7945         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7946          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7947         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7948         CryptDestroyKey(key);
7949         CertFreeCertificateContext(context);
7950     }
7951 }
7952
7953 static const char cspName[] = "WineCryptTemp";
7954
7955 static void testPortPublicKeyInfo(void)
7956 {
7957     HCRYPTPROV csp;
7958     BOOL ret;
7959     PCERT_PUBLIC_KEY_INFO info = NULL;
7960
7961     /* Just in case a previous run failed, delete this thing */
7962     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7963      CRYPT_DELETEKEYSET);
7964     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7965      CRYPT_NEWKEYSET);
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 }
7975
7976 START_TEST(encode)
7977 {
7978     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7979      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7980     HMODULE hCrypt32;
7981     DWORD i;
7982
7983     hCrypt32 = GetModuleHandleA("crypt32.dll");
7984     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7985     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7986     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7987     {
7988         win_skip("CryptDecodeObjectEx() is not available\n");
7989         return;
7990     }
7991
7992     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7993     {
7994         test_encodeInt(encodings[i]);
7995         test_decodeInt(encodings[i]);
7996         test_encodeEnumerated(encodings[i]);
7997         test_decodeEnumerated(encodings[i]);
7998         test_encodeFiletime(encodings[i]);
7999         test_decodeFiletime(encodings[i]);
8000         test_encodeName(encodings[i]);
8001         test_decodeName(encodings[i]);
8002         test_encodeUnicodeName(encodings[i]);
8003         test_decodeUnicodeName(encodings[i]);
8004         test_encodeNameValue(encodings[i]);
8005         test_decodeNameValue(encodings[i]);
8006         test_encodeUnicodeNameValue(encodings[i]);
8007         test_decodeUnicodeNameValue(encodings[i]);
8008         test_encodeAltName(encodings[i]);
8009         test_decodeAltName(encodings[i]);
8010         test_encodeOctets(encodings[i]);
8011         test_decodeOctets(encodings[i]);
8012         test_encodeBits(encodings[i]);
8013         test_decodeBits(encodings[i]);
8014         test_encodeBasicConstraints(encodings[i]);
8015         test_decodeBasicConstraints(encodings[i]);
8016         test_encodeRsaPublicKey(encodings[i]);
8017         test_decodeRsaPublicKey(encodings[i]);
8018         test_encodeSequenceOfAny(encodings[i]);
8019         test_decodeSequenceOfAny(encodings[i]);
8020         test_encodeExtensions(encodings[i]);
8021         test_decodeExtensions(encodings[i]);
8022         test_encodePublicKeyInfo(encodings[i]);
8023         test_decodePublicKeyInfo(encodings[i]);
8024         test_encodeCertToBeSigned(encodings[i]);
8025         test_decodeCertToBeSigned(encodings[i]);
8026         test_encodeCert(encodings[i]);
8027         test_decodeCert(encodings[i]);
8028         test_encodeCRLDistPoints(encodings[i]);
8029         test_decodeCRLDistPoints(encodings[i]);
8030         test_encodeCRLIssuingDistPoint(encodings[i]);
8031         test_decodeCRLIssuingDistPoint(encodings[i]);
8032         test_encodeCRLToBeSigned(encodings[i]);
8033         test_decodeCRLToBeSigned(encodings[i]);
8034         test_encodeEnhancedKeyUsage(encodings[i]);
8035         test_decodeEnhancedKeyUsage(encodings[i]);
8036         test_encodeAuthorityKeyId(encodings[i]);
8037         test_decodeAuthorityKeyId(encodings[i]);
8038         test_encodeAuthorityKeyId2(encodings[i]);
8039         test_decodeAuthorityKeyId2(encodings[i]);
8040         test_encodeAuthorityInfoAccess(encodings[i]);
8041         test_decodeAuthorityInfoAccess(encodings[i]);
8042         test_encodeCTL(encodings[i]);
8043         test_decodeCTL(encodings[i]);
8044         test_encodePKCSContentInfo(encodings[i]);
8045         test_decodePKCSContentInfo(encodings[i]);
8046         test_encodePKCSAttribute(encodings[i]);
8047         test_decodePKCSAttribute(encodings[i]);
8048         test_encodePKCSAttributes(encodings[i]);
8049         test_decodePKCSAttributes(encodings[i]);
8050         test_encodePKCSSMimeCapabilities(encodings[i]);
8051         test_decodePKCSSMimeCapabilities(encodings[i]);
8052         test_encodePKCSSignerInfo(encodings[i]);
8053         test_decodePKCSSignerInfo(encodings[i]);
8054         test_encodeCMSSignerInfo(encodings[i]);
8055         test_decodeCMSSignerInfo(encodings[i]);
8056         test_encodeNameConstraints(encodings[i]);
8057         test_decodeNameConstraints(encodings[i]);
8058         test_encodePolicyQualifierUserNotice(encodings[i]);
8059         test_decodePolicyQualifierUserNotice(encodings[i]);
8060         test_encodeCertPolicies(encodings[i]);
8061         test_decodeCertPolicies(encodings[i]);
8062         test_encodeCertPolicyMappings(encodings[i]);
8063         test_decodeCertPolicyMappings(encodings[i]);
8064         test_encodeCertPolicyConstraints(encodings[i]);
8065         test_decodeCertPolicyConstraints(encodings[i]);
8066     }
8067     testPortPublicKeyInfo();
8068 }