comctl32: Add implementation of LVS_EX_ONECLICKACTIVATE.
[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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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              (BYTE *)&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, (BYTE *)&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          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
667          GetLastError());
668     }
669 }
670
671 static const char commonName[] = "Juan Lang";
672 static const char surName[] = "Lang";
673
674 static const BYTE emptySequence[] = { 0x30, 0 };
675 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
676 static const BYTE twoRDNs[] = {
677     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
678     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
679     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
680 static const BYTE encodedTwoRDNs[] = {
681 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
682 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
683 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
684 0x6e,0x67,0x00,
685 };
686
687 static const BYTE us[] = { 0x55, 0x53 };
688 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
689  0x74, 0x61 };
690 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
691  0x6f, 0x6c, 0x69, 0x73 };
692 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
693  0x76, 0x65, 0x72, 0x73 };
694 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
695  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
696 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
697  0x73, 0x74 };
698 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
699  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
700
701 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
702 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
703
704 static CHAR oid_us[]            = "2.5.4.6",
705             oid_minnesota[]     = "2.5.4.8",
706             oid_minneapolis[]   = "2.5.4.7",
707             oid_codeweavers[]   = "2.5.4.10",
708             oid_wine[]          = "2.5.4.11",
709             oid_localhostAttr[] = "2.5.4.3",
710             oid_aric[]          = "1.2.840.113549.1.9.1";
711 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
712                                     { RDNA(minnesota) },
713                                     { RDNA(minneapolis) },
714                                     { RDNA(codeweavers) },
715                                     { RDNA(wine) },
716                                     { RDNA(localhostAttr) },
717                                     { RDNIA5(aric) } };
718 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
719                                            { RDNA(localhostAttr) },
720                                            { RDNA(minnesota) },
721                                            { RDNA(minneapolis) },
722                                            { RDNA(codeweavers) },
723                                            { RDNA(wine) },
724                                            { RDNIA5(aric) } };
725
726 #undef RDNIA5
727 #undef RDNA
728
729 static const BYTE encodedRDNAttrs[] = {
730 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
731 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
732 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
733 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
734 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
735 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
736 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
737 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
738 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
739 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
740 };
741
742 static void test_encodeName(DWORD dwEncoding)
743 {
744     CERT_RDN_ATTR attrs[2];
745     CERT_RDN rdn;
746     CERT_NAME_INFO info;
747     static CHAR oid_common_name[] = szOID_COMMON_NAME,
748                 oid_sur_name[]    = szOID_SUR_NAME;
749     BYTE *buf = NULL;
750     DWORD size = 0;
751     BOOL ret;
752
753     if (0)
754     {
755         /* Test with NULL pvStructInfo (crashes on win9x) */
756         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
757          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
758         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
759          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
760     }
761     /* Test with empty CERT_NAME_INFO */
762     info.cRDN = 0;
763     info.rgRDN = NULL;
764     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
765      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
766     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
767     if (buf)
768     {
769         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
770          "Got unexpected encoding for empty name\n");
771         LocalFree(buf);
772     }
773     if (0)
774     {
775         /* Test with bogus CERT_RDN (crashes on win9x) */
776         info.cRDN = 1;
777         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
778          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
779         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
780          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
781     }
782     /* Test with empty CERT_RDN */
783     rdn.cRDNAttr = 0;
784     rdn.rgRDNAttr = NULL;
785     info.cRDN = 1;
786     info.rgRDN = &rdn;
787     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
788      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
789     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
790     if (buf)
791     {
792         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
793          "Got unexpected encoding for empty RDN array\n");
794         LocalFree(buf);
795     }
796     if (0)
797     {
798         /* Test with bogus attr array (crashes on win9x) */
799         rdn.cRDNAttr = 1;
800         rdn.rgRDNAttr = NULL;
801         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
802          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
803         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
804          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
805     }
806     /* oddly, a bogus OID is accepted by Windows XP; not testing.
807     attrs[0].pszObjId = "bogus";
808     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
809     attrs[0].Value.cbData = sizeof(commonName);
810     attrs[0].Value.pbData = (BYTE *)commonName;
811     rdn.cRDNAttr = 1;
812     rdn.rgRDNAttr = attrs;
813     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
814      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
815     ok(!ret, "Expected failure, got success\n");
816      */
817     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
818      * the encoded attributes to be swapped.
819      */
820     attrs[0].pszObjId = oid_common_name;
821     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
822     attrs[0].Value.cbData = sizeof(commonName);
823     attrs[0].Value.pbData = (BYTE *)commonName;
824     attrs[1].pszObjId = oid_sur_name;
825     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
826     attrs[1].Value.cbData = sizeof(surName);
827     attrs[1].Value.pbData = (BYTE *)surName;
828     rdn.cRDNAttr = 2;
829     rdn.rgRDNAttr = attrs;
830     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
831      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
832     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
833     if (buf)
834     {
835         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
836          "Got unexpected encoding for two RDN array\n");
837         LocalFree(buf);
838     }
839     /* A name can be "encoded" with previously encoded RDN attrs. */
840     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
841     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
842     attrs[0].Value.cbData = sizeof(twoRDNs);
843     rdn.cRDNAttr = 1;
844     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
845      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
846     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
847     if (buf)
848     {
849         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
850         ok(!memcmp(buf, encodedTwoRDNs, size),
851          "Unexpected value for re-endoded two RDN array\n");
852         LocalFree(buf);
853     }
854     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
855     rdn.cRDNAttr = 1;
856     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
857     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
858      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
859     ok(!ret && GetLastError() == E_INVALIDARG,
860      "Expected E_INVALIDARG, got %08x\n", GetLastError());
861     /* Test a more complex name */
862     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
863     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
864     info.cRDN = 1;
865     info.rgRDN = &rdn;
866     buf = NULL;
867     size = 0;
868     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
869      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
870     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
871     if (ret)
872     {
873         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
874         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
875         LocalFree(buf);
876     }
877 }
878
879 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
880 static WCHAR surNameW[] = { 'L','a','n','g',0 };
881
882 static const BYTE twoRDNsNoNull[] = {
883  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
884  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
885  0x20,0x4c,0x61,0x6e,0x67 };
886 static const BYTE anyType[] = {
887  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
888  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
889  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
890  0x61,0x4c,0x67,0x6e };
891
892 static void test_encodeUnicodeName(DWORD dwEncoding)
893 {
894     CERT_RDN_ATTR attrs[2];
895     CERT_RDN rdn;
896     CERT_NAME_INFO info;
897     static CHAR oid_common_name[] = szOID_COMMON_NAME,
898                 oid_sur_name[]    = szOID_SUR_NAME;
899     BYTE *buf = NULL;
900     DWORD size = 0;
901     BOOL ret;
902
903     if (0)
904     {
905         /* Test with NULL pvStructInfo (crashes on win9x) */
906         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
907          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
908         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
909          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
910     }
911     /* Test with empty CERT_NAME_INFO */
912     info.cRDN = 0;
913     info.rgRDN = NULL;
914     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
915      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
916     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
917     if (buf)
918     {
919         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
920          "Got unexpected encoding for empty name\n");
921         LocalFree(buf);
922     }
923     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
924      * encoding (the NULL).
925      */
926     attrs[0].pszObjId = oid_common_name;
927     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
928     attrs[0].Value.cbData = sizeof(commonNameW);
929     attrs[0].Value.pbData = (BYTE *)commonNameW;
930     rdn.cRDNAttr = 1;
931     rdn.rgRDNAttr = attrs;
932     info.cRDN = 1;
933     info.rgRDN = &rdn;
934     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
935      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
936     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
937      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
938     ok(size == 9, "Unexpected error index %08x\n", size);
939     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
940      * forces the order of the encoded attributes to be swapped.
941      */
942     attrs[0].pszObjId = oid_common_name;
943     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
944     attrs[0].Value.cbData = 0;
945     attrs[0].Value.pbData = (BYTE *)commonNameW;
946     attrs[1].pszObjId = oid_sur_name;
947     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
948     attrs[1].Value.cbData = 0;
949     attrs[1].Value.pbData = (BYTE *)surNameW;
950     rdn.cRDNAttr = 2;
951     rdn.rgRDNAttr = attrs;
952     info.cRDN = 1;
953     info.rgRDN = &rdn;
954     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
955      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
956     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
957     if (buf)
958     {
959         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
960          "Got unexpected encoding for two RDN array\n");
961         LocalFree(buf);
962     }
963     /* A name can be "encoded" with previously encoded RDN attrs. */
964     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
965     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
966     attrs[0].Value.cbData = sizeof(twoRDNs);
967     rdn.cRDNAttr = 1;
968     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
969      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
970     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
971     if (buf)
972     {
973         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
974         ok(!memcmp(buf, encodedTwoRDNs, size),
975          "Unexpected value for re-endoded two RDN array\n");
976         LocalFree(buf);
977     }
978     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
979     rdn.cRDNAttr = 1;
980     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
981     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
982      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
983     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
984     if (buf)
985     {
986         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
987         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
988         LocalFree(buf);
989     }
990 }
991
992 static void compareNameValues(const CERT_NAME_VALUE *expected,
993  const CERT_NAME_VALUE *got)
994 {
995     ok(got->dwValueType == expected->dwValueType,
996      "Expected string type %d, got %d\n", expected->dwValueType,
997      got->dwValueType);
998     ok(got->Value.cbData == expected->Value.cbData,
999      "String type %d: unexpected data size, got %d, expected %d\n",
1000      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1001     if (got->Value.cbData && got->Value.pbData)
1002         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1003          min(got->Value.cbData, expected->Value.cbData)),
1004          "String type %d: unexpected value\n", expected->dwValueType);
1005 }
1006
1007 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1008  const CERT_RDN_ATTR *got)
1009 {
1010     if (expected->pszObjId && strlen(expected->pszObjId))
1011     {
1012         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1013          expected->pszObjId);
1014         if (got->pszObjId)
1015         {
1016             ok(!strcmp(got->pszObjId, expected->pszObjId),
1017              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1018              expected->pszObjId);
1019         }
1020     }
1021     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1022      (const CERT_NAME_VALUE *)&got->dwValueType);
1023 }
1024
1025 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1026 {
1027     ok(got->cRDNAttr == expected->cRDNAttr,
1028      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1029     if (got->cRDNAttr)
1030     {
1031         DWORD i;
1032
1033         for (i = 0; i < got->cRDNAttr; i++)
1034             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1035     }
1036 }
1037
1038 static void compareNames(const CERT_NAME_INFO *expected,
1039  const CERT_NAME_INFO *got)
1040 {
1041     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1042      expected->cRDN, got->cRDN);
1043     if (got->cRDN)
1044     {
1045         DWORD i;
1046
1047         for (i = 0; i < got->cRDN; i++)
1048             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1049     }
1050 }
1051
1052 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1053 static const BYTE twoRDNsExtraBytes[] = {
1054     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1055     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1056     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1057
1058 static void test_decodeName(DWORD dwEncoding)
1059 {
1060     BYTE *buf = NULL;
1061     DWORD bufSize = 0;
1062     BOOL ret;
1063     CERT_RDN rdn;
1064     CERT_NAME_INFO info = { 1, &rdn };
1065
1066     /* test empty name */
1067     bufSize = 0;
1068     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1069      emptySequence[1] + 2,
1070      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1071      (BYTE *)&buf, &bufSize);
1072     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1073     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1074      * decoder works the same way, so only test the count.
1075      */
1076     if (buf)
1077     {
1078         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1079         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1080          "Expected 0 RDNs in empty info, got %d\n",
1081          ((CERT_NAME_INFO *)buf)->cRDN);
1082         LocalFree(buf);
1083     }
1084     /* test empty name with indefinite-length encoding */
1085     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1086      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1087      (BYTE *)&buf, &bufSize);
1088     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1089     if (ret)
1090     {
1091         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1092         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1093          "Expected 0 RDNs in empty info, got %d\n",
1094          ((CERT_NAME_INFO *)buf)->cRDN);
1095         LocalFree(buf);
1096     }
1097     /* test empty RDN */
1098     bufSize = 0;
1099     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1100      emptyRDNs[1] + 2,
1101      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1102      (BYTE *)&buf, &bufSize);
1103     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1104     if (buf)
1105     {
1106         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1107
1108         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1109          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1110          "Got unexpected value for empty RDN\n");
1111         LocalFree(buf);
1112     }
1113     /* test two RDN attrs */
1114     bufSize = 0;
1115     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1116      twoRDNs[1] + 2,
1117      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1118      (BYTE *)&buf, &bufSize);
1119     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1120     if (buf)
1121     {
1122         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1123                     oid_common_name[] = szOID_COMMON_NAME;
1124
1125         CERT_RDN_ATTR attrs[] = {
1126          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1127           (BYTE *)surName } },
1128          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1129           (BYTE *)commonName } },
1130         };
1131
1132         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1133         rdn.rgRDNAttr = attrs;
1134         compareNames(&info, (CERT_NAME_INFO *)buf);
1135         LocalFree(buf);
1136     }
1137     /* test that two RDN attrs with extra bytes succeeds */
1138     bufSize = 0;
1139     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1140      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1141     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1142     /* And, a slightly more complicated name */
1143     buf = NULL;
1144     bufSize = 0;
1145     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1146      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1147     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1148     if (ret)
1149     {
1150         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1151         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1152         compareNames(&info, (CERT_NAME_INFO *)buf);
1153         LocalFree(buf);
1154     }
1155 }
1156
1157 static void test_decodeUnicodeName(DWORD dwEncoding)
1158 {
1159     BYTE *buf = NULL;
1160     DWORD bufSize = 0;
1161     BOOL ret;
1162     CERT_RDN rdn;
1163     CERT_NAME_INFO info = { 1, &rdn };
1164
1165     /* test empty name */
1166     bufSize = 0;
1167     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1168      emptySequence[1] + 2,
1169      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1170      (BYTE *)&buf, &bufSize);
1171     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1172     if (buf)
1173     {
1174         ok(bufSize == sizeof(CERT_NAME_INFO),
1175          "Got wrong bufSize %d\n", bufSize);
1176         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1177          "Expected 0 RDNs in empty info, got %d\n",
1178          ((CERT_NAME_INFO *)buf)->cRDN);
1179         LocalFree(buf);
1180     }
1181     /* test empty RDN */
1182     bufSize = 0;
1183     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1184      emptyRDNs[1] + 2,
1185      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1186      (BYTE *)&buf, &bufSize);
1187     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1188     if (buf)
1189     {
1190         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1191
1192         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1193          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1194          "Got unexpected value for empty RDN\n");
1195         LocalFree(buf);
1196     }
1197     /* test two RDN attrs */
1198     bufSize = 0;
1199     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1200      sizeof(twoRDNsNoNull),
1201      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1202      (BYTE *)&buf, &bufSize);
1203     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1204     if (buf)
1205     {
1206         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1207                     oid_common_name[] = szOID_COMMON_NAME;
1208
1209         CERT_RDN_ATTR attrs[] = {
1210          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1211          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1212          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1213          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1214         };
1215
1216         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1217         rdn.rgRDNAttr = attrs;
1218         compareNames(&info, (CERT_NAME_INFO *)buf);
1219         LocalFree(buf);
1220     }
1221 }
1222
1223 struct EncodedNameValue
1224 {
1225     CERT_NAME_VALUE value;
1226     const BYTE *encoded;
1227     DWORD encodedSize;
1228 };
1229
1230 static const char bogusIA5[] = "\x80";
1231 static const char bogusPrintable[] = "~";
1232 static const char bogusNumeric[] = "A";
1233 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1234 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1235 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1236 static BYTE octetCommonNameValue[] = {
1237  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1238 static BYTE numericCommonNameValue[] = {
1239  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1240 static BYTE printableCommonNameValue[] = {
1241  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1242 static BYTE t61CommonNameValue[] = {
1243  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1244 static BYTE videotexCommonNameValue[] = {
1245  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE ia5CommonNameValue[] = {
1247  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE graphicCommonNameValue[] = {
1249  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE visibleCommonNameValue[] = {
1251  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE generalCommonNameValue[] = {
1253  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE bmpCommonNameValue[] = {
1255  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1256  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1257 static BYTE utf8CommonNameValue[] = {
1258  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1259
1260 static struct EncodedNameValue nameValues[] = {
1261  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1262      octetCommonNameValue, sizeof(octetCommonNameValue) },
1263  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1264      numericCommonNameValue, sizeof(numericCommonNameValue) },
1265  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1266      printableCommonNameValue, sizeof(printableCommonNameValue) },
1267  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1268      t61CommonNameValue, sizeof(t61CommonNameValue) },
1269  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1271  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1273  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1275  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1277  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278      generalCommonNameValue, sizeof(generalCommonNameValue) },
1279  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1280      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1281  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1282      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1283  /* The following tests succeed under Windows, but really should fail,
1284   * they contain characters that are illegal for the encoding.  I'm
1285   * including them to justify my lazy encoding.
1286   */
1287  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1288      sizeof(bin42) },
1289  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1290      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1291  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1292      bin44, sizeof(bin44) },
1293 };
1294
1295 static void test_encodeNameValue(DWORD dwEncoding)
1296 {
1297     BYTE *buf = NULL;
1298     DWORD size = 0, i;
1299     BOOL ret;
1300     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1301
1302     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1303     value.Value.pbData = printableCommonNameValue;
1304     value.Value.cbData = sizeof(printableCommonNameValue);
1305     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1306      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1307     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1308     if (buf)
1309     {
1310         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1311          size);
1312         ok(!memcmp(buf, printableCommonNameValue, size),
1313          "Unexpected encoding\n");
1314         LocalFree(buf);
1315     }
1316     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1317     {
1318         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1319          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1320          &size);
1321         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1322          nameValues[i].value.dwValueType, GetLastError());
1323         if (buf)
1324         {
1325             ok(size == nameValues[i].encodedSize,
1326              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1327             ok(!memcmp(buf, nameValues[i].encoded, size),
1328              "Got unexpected encoding\n");
1329             LocalFree(buf);
1330         }
1331     }
1332 }
1333
1334 static void test_decodeNameValue(DWORD dwEncoding)
1335 {
1336     int i;
1337     BYTE *buf = NULL;
1338     DWORD bufSize = 0;
1339     BOOL ret;
1340
1341     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1342     {
1343         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1344          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1345          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1346          (BYTE *)&buf, &bufSize);
1347         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1348          nameValues[i].value.dwValueType, GetLastError());
1349         if (buf)
1350         {
1351             compareNameValues(&nameValues[i].value,
1352              (const CERT_NAME_VALUE *)buf);
1353             LocalFree(buf);
1354         }
1355     }
1356 }
1357
1358 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1359 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1360 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1361  'h','q','.','o','r','g',0 };
1362 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1363  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1364  0x6f, 0x72, 0x67 };
1365 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1366  0x575b, 0 };
1367 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1368 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1369  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1370 static const BYTE localhost[] = { 127, 0, 0, 1 };
1371 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1372  0x01 };
1373 static const unsigned char encodedCommonName[] = {
1374     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1375 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1376 static const BYTE encodedDirectoryName[] = {
1377 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1378 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1379
1380 static void test_encodeAltName(DWORD dwEncoding)
1381 {
1382     CERT_ALT_NAME_INFO info = { 0 };
1383     CERT_ALT_NAME_ENTRY entry = { 0 };
1384     BYTE *buf = NULL;
1385     DWORD size = 0;
1386     BOOL ret;
1387     char oid[] = "1.2.3";
1388
1389     /* Test with empty info */
1390     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1391      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1392     if (buf)
1393     {
1394         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1395         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1396         LocalFree(buf);
1397     }
1398     /* Test with an empty entry */
1399     info.cAltEntry = 1;
1400     info.rgAltEntry = &entry;
1401     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1402      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1403     ok(!ret && GetLastError() == E_INVALIDARG,
1404      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1405     /* Test with an empty pointer */
1406     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1407     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1408      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1409     if (buf)
1410     {
1411         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1412         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1413         LocalFree(buf);
1414     }
1415     /* Test with a real URL */
1416     U(entry).pwszURL = (LPWSTR)url;
1417     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1418      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1419     if (buf)
1420     {
1421         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1422         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1423         LocalFree(buf);
1424     }
1425     /* Now with the URL containing an invalid IA5 char */
1426     U(entry).pwszURL = (LPWSTR)nihongoURL;
1427     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1428      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1429     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1430      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1431     /* The first invalid character is at index 7 */
1432     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1433      "Expected invalid char at index 7, got %d\n",
1434      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1435     /* Now with the URL missing a scheme */
1436     U(entry).pwszURL = (LPWSTR)dnsName;
1437     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1438      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1439     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1440     if (buf)
1441     {
1442         /* This succeeds, but it shouldn't, so don't worry about conforming */
1443         LocalFree(buf);
1444     }
1445     /* Now with a DNS name */
1446     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1447     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1448      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1449     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1450     if (buf)
1451     {
1452         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1453         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1454         LocalFree(buf);
1455     }
1456     /* Test with an IP address */
1457     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1458     U(entry).IPAddress.cbData = sizeof(localhost);
1459     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1460     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1461      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1462     if (buf)
1463     {
1464         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1465         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1466         LocalFree(buf);
1467     }
1468     /* Test with OID */
1469     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1470     U(entry).pszRegisteredID = oid;
1471     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1472      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1473     if (buf)
1474     {
1475         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1476         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1477         LocalFree(buf);
1478     }
1479     /* Test with directory name */
1480     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1481     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1482     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1483     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1484      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1485     if (buf)
1486     {
1487         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1488         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1489         LocalFree(buf);
1490     }
1491 }
1492
1493 static void test_decodeAltName(DWORD dwEncoding)
1494 {
1495     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1496      0x00, 0x00, 0x01 };
1497     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1498      0x01 };
1499     BOOL ret;
1500     BYTE *buf = NULL;
1501     DWORD bufSize = 0;
1502     CERT_ALT_NAME_INFO *info;
1503
1504     /* Test some bogus ones first */
1505     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1506      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1507      NULL, (BYTE *)&buf, &bufSize);
1508     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1509      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1510      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1511      GetLastError());
1512     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1513      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1514      &bufSize);
1515     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1516      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1517      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1518      GetLastError());
1519     /* Now expected cases */
1520     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1521      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1522      &bufSize);
1523     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1524     if (buf)
1525     {
1526         info = (CERT_ALT_NAME_INFO *)buf;
1527
1528         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1529          info->cAltEntry);
1530         LocalFree(buf);
1531     }
1532     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1533      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1534      &bufSize);
1535     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1536     if (buf)
1537     {
1538         info = (CERT_ALT_NAME_INFO *)buf;
1539
1540         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1541          info->cAltEntry);
1542         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1543          "Expected CERT_ALT_NAME_URL, got %d\n",
1544          info->rgAltEntry[0].dwAltNameChoice);
1545         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1546          "Expected empty URL\n");
1547         LocalFree(buf);
1548     }
1549     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1550      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1551     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1552     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1553      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1554      &bufSize);
1555     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1556     if (buf)
1557     {
1558         info = (CERT_ALT_NAME_INFO *)buf;
1559
1560         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1561          info->cAltEntry);
1562         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1563          "Expected CERT_ALT_NAME_URL, got %d\n",
1564          info->rgAltEntry[0].dwAltNameChoice);
1565         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1566         LocalFree(buf);
1567     }
1568     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1569      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1570      &bufSize);
1571     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1572     if (buf)
1573     {
1574         info = (CERT_ALT_NAME_INFO *)buf;
1575
1576         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1577          info->cAltEntry);
1578         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1579          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1580          info->rgAltEntry[0].dwAltNameChoice);
1581         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1582          "Unexpected DNS name\n");
1583         LocalFree(buf);
1584     }
1585     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1586      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1587      &bufSize);
1588     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1589     if (buf)
1590     {
1591         info = (CERT_ALT_NAME_INFO *)buf;
1592
1593         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1594          info->cAltEntry);
1595         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1596          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1597          info->rgAltEntry[0].dwAltNameChoice);
1598         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1599          "Unexpected IP address length %d\n",
1600           U(info->rgAltEntry[0]).IPAddress.cbData);
1601         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1602          sizeof(localhost)), "Unexpected IP address value\n");
1603         LocalFree(buf);
1604     }
1605     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1606      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1607      &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_REGISTERED_ID,
1616          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1617          info->rgAltEntry[0].dwAltNameChoice);
1618         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1619            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1620         LocalFree(buf);
1621     }
1622     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1623      encodedDirectoryName, sizeof(encodedDirectoryName),
1624      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1625     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1626     if (buf)
1627     {
1628         info = (CERT_ALT_NAME_INFO *)buf;
1629
1630         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1631          info->cAltEntry);
1632         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1633          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1634          info->rgAltEntry[0].dwAltNameChoice);
1635         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1636          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1637           U(info->rgAltEntry[0]).DirectoryName.cbData);
1638         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1639          encodedCommonName, sizeof(encodedCommonName)),
1640          "Unexpected directory name value\n");
1641         LocalFree(buf);
1642     }
1643 }
1644
1645 struct UnicodeExpectedError
1646 {
1647     DWORD   valueType;
1648     LPCWSTR str;
1649     DWORD   errorIndex;
1650     DWORD   error;
1651 };
1652
1653 static const WCHAR oneW[] = { '1',0 };
1654 static const WCHAR aW[] = { 'a',0 };
1655 static const WCHAR quoteW[] = { '"', 0 };
1656
1657 static struct UnicodeExpectedError unicodeErrors[] = {
1658  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1659  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1660  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1661  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1662  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1663  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1664 };
1665
1666 struct UnicodeExpectedResult
1667 {
1668     DWORD           valueType;
1669     LPCWSTR         str;
1670     CRYPT_DATA_BLOB encoded;
1671 };
1672
1673 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1674 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1675 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1676 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1677 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1678 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1679 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1680 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1681 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1682 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1683 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1684 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1685  0x5b };
1686 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1687  0x6f,0x5b };
1688 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1689  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1690 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1691  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1692
1693 static struct UnicodeExpectedResult unicodeResults[] = {
1694  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1695  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1696  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1697  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1698  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1699  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1700  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1701  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1702  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1703  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1704  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1705  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1706  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1707 };
1708
1709 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1710  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1711  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1712 };
1713
1714 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1715 {
1716     BYTE *buf = NULL;
1717     DWORD size = 0, i;
1718     BOOL ret;
1719     CERT_NAME_VALUE value;
1720
1721     if (0)
1722     {
1723         /* Crashes on win9x */
1724         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1725          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1726         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1727          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1728     }
1729     /* Have to have a string of some sort */
1730     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1731     value.Value.pbData = NULL;
1732     value.Value.cbData = 0;
1733     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1734      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1735     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1736      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1737     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1738     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1739      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1740     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1741      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1742     value.dwValueType = CERT_RDN_ANY_TYPE;
1743     value.Value.pbData = (LPBYTE)oneW;
1744     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1745      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1746     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1747      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1748     value.Value.cbData = sizeof(oneW);
1749     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1750      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1751     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1752      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1753     /* An encoded string with specified length isn't good enough either */
1754     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1755     value.Value.pbData = oneUniversal;
1756     value.Value.cbData = sizeof(oneUniversal);
1757     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1758      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1759     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1760      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1761     /* More failure checking */
1762     value.Value.cbData = 0;
1763     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1764     {
1765         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1766         value.dwValueType = unicodeErrors[i].valueType;
1767         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1768          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1769         ok(!ret && GetLastError() == unicodeErrors[i].error,
1770          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1771          unicodeErrors[i].error, GetLastError());
1772         ok(size == unicodeErrors[i].errorIndex,
1773          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1774          size);
1775     }
1776     /* cbData can be zero if the string is NULL-terminated */
1777     value.Value.cbData = 0;
1778     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1779     {
1780         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1781         value.dwValueType = unicodeResults[i].valueType;
1782         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1783          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1784         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1785          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1786         if (buf)
1787         {
1788             ok(size == unicodeResults[i].encoded.cbData,
1789              "Value type %d: expected size %d, got %d\n",
1790              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1791             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1792              "Value type %d: unexpected value\n", value.dwValueType);
1793             LocalFree(buf);
1794         }
1795     }
1796     /* These "encode," but they do so by truncating each unicode character
1797      * rather than properly encoding it.  Kept separate from the proper results,
1798      * because the encoded forms won't decode to their original strings.
1799      */
1800     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1801     {
1802         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1803         value.dwValueType = unicodeWeirdness[i].valueType;
1804         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1805          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1806         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1807         if (buf)
1808         {
1809             ok(size == unicodeWeirdness[i].encoded.cbData,
1810              "Value type %d: expected size %d, got %d\n",
1811              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1812             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1813              "Value type %d: unexpected value\n", value.dwValueType);
1814             LocalFree(buf);
1815         }
1816     }
1817 }
1818
1819 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1820 {
1821     if (n <= 0) return 0;
1822     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1823     return *str1 - *str2;
1824 }
1825
1826 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1827 {
1828     DWORD i;
1829
1830     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1831     {
1832         BYTE *buf = NULL;
1833         BOOL ret;
1834         DWORD size = 0;
1835
1836         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1837          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1838          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1839         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1840          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1841         if (ret && buf)
1842         {
1843             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1844
1845             ok(value->dwValueType == unicodeResults[i].valueType,
1846              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1847              value->dwValueType);
1848             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1849              value->Value.cbData / sizeof(WCHAR)),
1850              "Unexpected decoded value for index %d (value type %d)\n", i,
1851              unicodeResults[i].valueType);
1852             LocalFree(buf);
1853         }
1854     }
1855 }
1856
1857 struct encodedOctets
1858 {
1859     const BYTE *val;
1860     const BYTE *encoded;
1861 };
1862
1863 static const unsigned char bin46[] = { 'h','i',0 };
1864 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1865 static const unsigned char bin48[] = {
1866      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1867 static const unsigned char bin49[] = {
1868      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin50[] = { 0 };
1870 static const unsigned char bin51[] = { 0x04,0x00,0 };
1871
1872 static const struct encodedOctets octets[] = {
1873     { bin46, bin47 },
1874     { bin48, bin49 },
1875     { bin50, bin51 },
1876 };
1877
1878 static void test_encodeOctets(DWORD dwEncoding)
1879 {
1880     CRYPT_DATA_BLOB blob;
1881     DWORD i;
1882
1883     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1884     {
1885         BYTE *buf = NULL;
1886         BOOL ret;
1887         DWORD bufSize = 0;
1888
1889         blob.cbData = strlen((const char*)octets[i].val);
1890         blob.pbData = (BYTE*)octets[i].val;
1891         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1892          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1893         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1894         if (buf)
1895         {
1896             ok(buf[0] == 4,
1897              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1898             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1899              buf[1], octets[i].encoded[1]);
1900             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1901              octets[i].encoded[1] + 1), "Got unexpected value\n");
1902             LocalFree(buf);
1903         }
1904     }
1905 }
1906
1907 static void test_decodeOctets(DWORD dwEncoding)
1908 {
1909     DWORD i;
1910
1911     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1912     {
1913         BYTE *buf = NULL;
1914         BOOL ret;
1915         DWORD bufSize = 0;
1916
1917         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1918          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1919          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1920         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1921         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1922          "Expected size >= %d, got %d\n",
1923            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1924         ok(buf != NULL, "Expected allocated buffer\n");
1925         if (buf)
1926         {
1927             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1928
1929             if (blob->cbData)
1930                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1931                  "Unexpected value\n");
1932             LocalFree(buf);
1933         }
1934     }
1935 }
1936
1937 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1938
1939 struct encodedBits
1940 {
1941     DWORD cUnusedBits;
1942     const BYTE *encoded;
1943     DWORD cbDecoded;
1944     const BYTE *decoded;
1945 };
1946
1947 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1948 static const unsigned char bin53[] = { 0xff,0xff };
1949 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1950 static const unsigned char bin55[] = { 0xff,0xfe };
1951 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1952 static const unsigned char bin57[] = { 0xfe };
1953 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1954
1955 static const struct encodedBits bits[] = {
1956     /* normal test cases */
1957     { 0, bin52, 2, bin53 },
1958     { 1, bin54, 2, bin55 },
1959     /* strange test case, showing cUnusedBits >= 8 is allowed */
1960     { 9, bin56, 1, bin57 },
1961     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1962     { 17, bin58, 0, NULL },
1963 };
1964
1965 static void test_encodeBits(DWORD dwEncoding)
1966 {
1967     DWORD i;
1968
1969     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1970     {
1971         CRYPT_BIT_BLOB blob;
1972         BOOL ret;
1973         BYTE *buf = NULL;
1974         DWORD bufSize = 0;
1975
1976         blob.cbData = sizeof(bytesToEncode);
1977         blob.pbData = (BYTE *)bytesToEncode;
1978         blob.cUnusedBits = bits[i].cUnusedBits;
1979         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1980          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1981         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1982         if (buf)
1983         {
1984             ok(bufSize == bits[i].encoded[1] + 2,
1985              "Got unexpected size %d, expected %d\n", bufSize,
1986              bits[i].encoded[1] + 2);
1987             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1988              "Unexpected value\n");
1989             LocalFree(buf);
1990         }
1991     }
1992 }
1993
1994 static void test_decodeBits(DWORD dwEncoding)
1995 {
1996     static const BYTE ber[] = "\x03\x02\x01\xff";
1997     static const BYTE berDecoded = 0xfe;
1998     DWORD i;
1999     BOOL ret;
2000     BYTE *buf = NULL;
2001     DWORD bufSize = 0;
2002
2003     /* normal cases */
2004     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2005     {
2006         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2007          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2008          &bufSize);
2009         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2010         if (buf)
2011         {
2012             CRYPT_BIT_BLOB *blob;
2013
2014             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2015                "Got unexpected size %d\n", bufSize);
2016             blob = (CRYPT_BIT_BLOB *)buf;
2017             ok(blob->cbData == bits[i].cbDecoded,
2018              "Got unexpected length %d, expected %d\n", blob->cbData,
2019              bits[i].cbDecoded);
2020             if (blob->cbData && bits[i].cbDecoded)
2021                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2022                  "Unexpected value\n");
2023             LocalFree(buf);
2024         }
2025     }
2026     /* special case: check that something that's valid in BER but not in DER
2027      * decodes successfully
2028      */
2029     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2030      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2031     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2032     if (buf)
2033     {
2034         CRYPT_BIT_BLOB *blob;
2035
2036         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2037            "Got unexpected size %d\n", bufSize);
2038         blob = (CRYPT_BIT_BLOB *)buf;
2039         ok(blob->cbData == sizeof(berDecoded),
2040            "Got unexpected length %d\n", blob->cbData);
2041         if (blob->cbData)
2042             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2043         LocalFree(buf);
2044     }
2045 }
2046
2047 struct Constraints2
2048 {
2049     CERT_BASIC_CONSTRAINTS2_INFO info;
2050     const BYTE *encoded;
2051 };
2052
2053 static const unsigned char bin59[] = { 0x30,0x00 };
2054 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2055 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2056 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2057 static const struct Constraints2 constraints2[] = {
2058  /* empty constraints */
2059  { { FALSE, FALSE, 0}, bin59 },
2060  /* can be a CA */
2061  { { TRUE,  FALSE, 0}, bin60 },
2062  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2063   * but that's not the case
2064   */
2065  { { FALSE, TRUE,  0}, bin61 },
2066  /* can be a CA and has path length constraints set */
2067  { { TRUE,  TRUE,  1}, bin62 },
2068 };
2069
2070 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2071 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2072  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2073  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2074  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2075 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2076  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2077  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2078  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2079  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2080
2081 static void test_encodeBasicConstraints(DWORD dwEncoding)
2082 {
2083     DWORD i, bufSize = 0;
2084     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2085     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2086      (LPBYTE)encodedDomainName };
2087     BOOL ret;
2088     BYTE *buf = NULL;
2089
2090     /* First test with the simpler info2 */
2091     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2092     {
2093         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2094          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2095          &bufSize);
2096         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2097         if (buf)
2098         {
2099             ok(bufSize == constraints2[i].encoded[1] + 2,
2100              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2101              bufSize);
2102             ok(!memcmp(buf, constraints2[i].encoded,
2103              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2104             LocalFree(buf);
2105         }
2106     }
2107     /* Now test with more complex basic constraints */
2108     info.SubjectType.cbData = 0;
2109     info.fPathLenConstraint = FALSE;
2110     info.cSubtreesConstraint = 0;
2111     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2112      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2113     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2114      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2115     if (buf)
2116     {
2117         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2118         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2119          "Unexpected value\n");
2120         LocalFree(buf);
2121     }
2122     /* None of the certs I examined had any subtree constraint, but I test one
2123      * anyway just in case.
2124      */
2125     info.cSubtreesConstraint = 1;
2126     info.rgSubtreesConstraint = &nameBlob;
2127     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2128      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2129     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2130      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2131     if (buf)
2132     {
2133         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2134         ok(!memcmp(buf, constraintWithDomainName,
2135          sizeof(constraintWithDomainName)), "Unexpected value\n");
2136         LocalFree(buf);
2137     }
2138     /* FIXME: test encoding with subject type. */
2139 }
2140
2141 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2142
2143 static void test_decodeBasicConstraints(DWORD dwEncoding)
2144 {
2145     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2146      0xff };
2147     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2148     DWORD i;
2149     BOOL ret;
2150     BYTE *buf = NULL;
2151     DWORD bufSize = 0;
2152
2153     /* First test with simpler info2 */
2154     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2155     {
2156         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2157          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2158          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2159         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2160          GetLastError());
2161         if (buf)
2162         {
2163             CERT_BASIC_CONSTRAINTS2_INFO *info =
2164              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2165
2166             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2167              "Unexpected value for item %d\n", i);
2168             LocalFree(buf);
2169         }
2170     }
2171     /* Check with the order of encoded elements inverted */
2172     buf = (PBYTE)1;
2173     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2174      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2175      &bufSize);
2176     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2177      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2178      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2179      GetLastError());
2180     ok(!buf, "Expected buf to be set to NULL\n");
2181     /* Check with a non-DER bool */
2182     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2183      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2184      (BYTE *)&buf, &bufSize);
2185     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2186     if (buf)
2187     {
2188         CERT_BASIC_CONSTRAINTS2_INFO *info =
2189          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2190
2191         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2192         LocalFree(buf);
2193     }
2194     /* Check with a non-basic constraints value */
2195     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2197      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2198     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2199      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2200      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2201      GetLastError());
2202     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2203     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2204      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2205      (BYTE *)&buf, &bufSize);
2206     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207     if (buf)
2208     {
2209         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2210
2211         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2212         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2213         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2214         LocalFree(buf);
2215     }
2216     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2217      constraintWithDomainName, sizeof(constraintWithDomainName),
2218      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2219     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2220     if (buf)
2221     {
2222         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2223
2224         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2225         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2226         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2227         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2228         {
2229             ok(info->rgSubtreesConstraint[0].cbData ==
2230              sizeof(encodedDomainName), "Wrong size %d\n",
2231              info->rgSubtreesConstraint[0].cbData);
2232             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2233              sizeof(encodedDomainName)), "Unexpected value\n");
2234         }
2235         LocalFree(buf);
2236     }
2237 }
2238
2239 /* These are terrible public keys of course, I'm just testing encoding */
2240 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2241 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2242 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2243 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2244 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2245 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2246 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2248
2249 struct EncodedRSAPubKey
2250 {
2251     const BYTE *modulus;
2252     size_t modulusLen;
2253     const BYTE *encoded;
2254     size_t decodedModulusLen;
2255 };
2256
2257 struct EncodedRSAPubKey rsaPubKeys[] = {
2258     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2259     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2260     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2261     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2262 };
2263
2264 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2265 {
2266     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2267     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2268     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2269     BOOL ret;
2270     BYTE *buf = NULL;
2271     DWORD bufSize = 0, i;
2272
2273     /* Try with a bogus blob type */
2274     hdr->bType = 2;
2275     hdr->bVersion = CUR_BLOB_VERSION;
2276     hdr->reserved = 0;
2277     hdr->aiKeyAlg = CALG_RSA_KEYX;
2278     rsaPubKey->magic = 0x31415352;
2279     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2280     rsaPubKey->pubexp = 65537;
2281     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2282      sizeof(modulus1));
2283
2284     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2285      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2286      &bufSize);
2287     ok(!ret && GetLastError() == E_INVALIDARG,
2288      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2289     /* Now with a bogus reserved field */
2290     hdr->bType = PUBLICKEYBLOB;
2291     hdr->reserved = 1;
2292     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2293      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2294      &bufSize);
2295     if (buf)
2296     {
2297         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2298          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2299         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2300         LocalFree(buf);
2301     }
2302     /* Now with a bogus blob version */
2303     hdr->reserved = 0;
2304     hdr->bVersion = 0;
2305     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2306      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2307      &bufSize);
2308     if (buf)
2309     {
2310         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2311          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2312         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2313         LocalFree(buf);
2314     }
2315     /* And with a bogus alg ID */
2316     hdr->bVersion = CUR_BLOB_VERSION;
2317     hdr->aiKeyAlg = CALG_DES;
2318     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2319      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2320      &bufSize);
2321     if (buf)
2322     {
2323         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2324          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2325         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2326         LocalFree(buf);
2327     }
2328     /* Check a couple of RSA-related OIDs */
2329     hdr->aiKeyAlg = CALG_RSA_KEYX;
2330     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2331      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2332     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2335      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2336     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2337      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2338     /* Finally, all valid */
2339     hdr->aiKeyAlg = CALG_RSA_KEYX;
2340     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2341     {
2342         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2343          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2344         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2345          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2346         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2347         if (buf)
2348         {
2349             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2350              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2351              bufSize);
2352             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2353              "Unexpected value\n");
2354             LocalFree(buf);
2355         }
2356     }
2357 }
2358
2359 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2360 {
2361     DWORD i;
2362     LPBYTE buf = NULL;
2363     DWORD bufSize = 0;
2364     BOOL ret;
2365
2366     /* Try with a bad length */
2367     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2368      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2369      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2370     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2371      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2372     /* Try with a couple of RSA-related OIDs */
2373     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2374      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2375      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2376     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2377      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2378     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2379      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2380      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2381     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2382      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2383     /* Now try success cases */
2384     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2385     {
2386         bufSize = 0;
2387         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2388          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2389          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2390         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2391         if (buf)
2392         {
2393             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2394             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2395
2396             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2397              rsaPubKeys[i].decodedModulusLen,
2398              "Wrong size %d\n", bufSize);
2399             ok(hdr->bType == PUBLICKEYBLOB,
2400              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2401              hdr->bType);
2402             ok(hdr->bVersion == CUR_BLOB_VERSION,
2403              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2404              CUR_BLOB_VERSION, hdr->bVersion);
2405             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2406              hdr->reserved);
2407             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2408              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2409             ok(rsaPubKey->magic == 0x31415352,
2410              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2411             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2412              "Wrong bit len %d\n", rsaPubKey->bitlen);
2413             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2414              rsaPubKey->pubexp);
2415             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2416              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2417              "Unexpected modulus\n");
2418             LocalFree(buf);
2419         }
2420     }
2421 }
2422
2423 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2424  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2425  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2426
2427 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2428  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2429  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2430  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2431
2432 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2433 {
2434     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2435     CRYPT_SEQUENCE_OF_ANY seq;
2436     DWORD i;
2437     BOOL ret;
2438     BYTE *buf = NULL;
2439     DWORD bufSize = 0;
2440
2441     /* Encode a homogeneous sequence */
2442     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2443     {
2444         blobs[i].cbData = ints[i].encoded[1] + 2;
2445         blobs[i].pbData = (BYTE *)ints[i].encoded;
2446     }
2447     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2448     seq.rgValue = blobs;
2449
2450     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2451      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2452     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2453     if (buf)
2454     {
2455         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2456         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2457         LocalFree(buf);
2458     }
2459     /* Change the type of the first element in the sequence, and give it
2460      * another go
2461      */
2462     blobs[0].cbData = times[0].encodedTime[1] + 2;
2463     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2464     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2465      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2466     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2467     if (buf)
2468     {
2469         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2470         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2471          "Unexpected value\n");
2472         LocalFree(buf);
2473     }
2474 }
2475
2476 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2477 {
2478     BOOL ret;
2479     BYTE *buf = NULL;
2480     DWORD bufSize = 0;
2481
2482     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2483      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2484     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2485     if (buf)
2486     {
2487         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2488         DWORD i;
2489
2490         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2491          "Wrong elements %d\n", seq->cValue);
2492         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2493         {
2494             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2495              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2496              seq->rgValue[i].cbData);
2497             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2498              ints[i].encoded[1] + 2), "Unexpected value\n");
2499         }
2500         LocalFree(buf);
2501     }
2502     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2503      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2504      &bufSize);
2505     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2506     if (buf)
2507     {
2508         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2509
2510         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2511          "Wrong elements %d\n", seq->cValue);
2512         /* Just check the first element since it's all that changed */
2513         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2514          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2515          seq->rgValue[0].cbData);
2516         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2517          times[0].encodedTime[1] + 2), "Unexpected value\n");
2518         LocalFree(buf);
2519     }
2520 }
2521
2522 struct encodedExtensions
2523 {
2524     CERT_EXTENSIONS exts;
2525     const BYTE *encoded;
2526 };
2527
2528 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2529 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2530 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2531 static CERT_EXTENSION criticalExt =
2532  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2533 static CERT_EXTENSION nonCriticalExt =
2534  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2535
2536 static const BYTE ext0[] = { 0x30,0x00 };
2537 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2538                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2539 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2540                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2541
2542 static const struct encodedExtensions exts[] = {
2543  { { 0, NULL }, ext0 },
2544  { { 1, &criticalExt }, ext1 },
2545  { { 1, &nonCriticalExt }, ext2 },
2546 };
2547
2548 static void test_encodeExtensions(DWORD dwEncoding)
2549 {
2550     DWORD i;
2551
2552     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2553     {
2554         BOOL ret;
2555         BYTE *buf = NULL;
2556         DWORD bufSize = 0;
2557
2558         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2559          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2560         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2561         if (buf)
2562         {
2563             ok(bufSize == exts[i].encoded[1] + 2,
2564              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2565             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2566              "Unexpected value\n");
2567             LocalFree(buf);
2568         }
2569     }
2570 }
2571
2572 static void test_decodeExtensions(DWORD dwEncoding)
2573 {
2574     DWORD i;
2575
2576     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2577     {
2578         BOOL ret;
2579         BYTE *buf = NULL;
2580         DWORD bufSize = 0;
2581
2582         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2583          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2584          NULL, (BYTE *)&buf, &bufSize);
2585         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2586         if (buf)
2587         {
2588             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2589             DWORD j;
2590
2591             ok(ext->cExtension == exts[i].exts.cExtension,
2592              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2593              ext->cExtension);
2594             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2595             {
2596                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2597                  exts[i].exts.rgExtension[j].pszObjId),
2598                  "Expected OID %s, got %s\n",
2599                  exts[i].exts.rgExtension[j].pszObjId,
2600                  ext->rgExtension[j].pszObjId);
2601                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2602                  exts[i].exts.rgExtension[j].Value.pbData,
2603                  exts[i].exts.rgExtension[j].Value.cbData),
2604                  "Unexpected value\n");
2605             }
2606             LocalFree(buf);
2607         }
2608     }
2609 }
2610
2611 /* MS encodes public key info with a NULL if the algorithm identifier's
2612  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2613  * it encodes them by omitting the algorithm parameters.  This latter approach
2614  * seems more correct, so accept either form.
2615  */
2616 struct encodedPublicKey
2617 {
2618     CERT_PUBLIC_KEY_INFO info;
2619     const BYTE *encoded;
2620     const BYTE *encodedNoNull;
2621     CERT_PUBLIC_KEY_INFO decoded;
2622 };
2623
2624 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2625  0xe, 0xf };
2626 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2627
2628 static const unsigned char bin64[] = {
2629     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2630 static const unsigned char bin65[] = {
2631     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2632 static const unsigned char bin66[] = {
2633     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2634 static const unsigned char bin67[] = {
2635     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2636 static const unsigned char bin68[] = {
2637     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2638     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2639 static const unsigned char bin69[] = {
2640     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2641     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2642 static const unsigned char bin70[] = {
2643     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2644     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2645     0x0f};
2646 static const unsigned char bin71[] = {
2647     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2648     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2649     0x0f};
2650 static unsigned char bin72[] = { 0x05,0x00};
2651
2652 static CHAR oid_bogus[] = "1.2.3",
2653             oid_rsa[]   = szOID_RSA;
2654
2655 static const struct encodedPublicKey pubKeys[] = {
2656  /* with a bogus OID */
2657  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2658   bin64, bin65,
2659   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2660  /* some normal keys */
2661  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2662   bin66, bin67,
2663   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2664  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2665   bin68, bin69,
2666   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2667  /* with add'l parameters--note they must be DER-encoded */
2668  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2669   (BYTE *)aKey, 0 } },
2670   bin70, bin71,
2671   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2672   (BYTE *)aKey, 0 } } },
2673 };
2674
2675 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2676 {
2677     DWORD i;
2678
2679     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2680     {
2681         BOOL ret;
2682         BYTE *buf = NULL;
2683         DWORD bufSize = 0;
2684
2685         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2686          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2687          &bufSize);
2688         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2689          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2690         if (buf)
2691         {
2692             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2693              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2694              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2695              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2696             if (bufSize == pubKeys[i].encoded[1] + 2)
2697                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2698                  "Unexpected value\n");
2699             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2700                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2701                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2702             LocalFree(buf);
2703         }
2704     }
2705 }
2706
2707 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2708  const CERT_PUBLIC_KEY_INFO *got)
2709 {
2710     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2711      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2712      got->Algorithm.pszObjId);
2713     ok(expected->Algorithm.Parameters.cbData ==
2714      got->Algorithm.Parameters.cbData,
2715      "Expected parameters of %d bytes, got %d\n",
2716      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2717     if (expected->Algorithm.Parameters.cbData)
2718         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2719          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2720          "Unexpected algorithm parameters\n");
2721     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2722      "Expected public key of %d bytes, got %d\n",
2723      expected->PublicKey.cbData, got->PublicKey.cbData);
2724     if (expected->PublicKey.cbData)
2725         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2726          got->PublicKey.cbData), "Unexpected public key value\n");
2727 }
2728
2729 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2730 {
2731     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2732      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2733      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2734      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2735     DWORD i;
2736     BOOL ret;
2737     BYTE *buf = NULL;
2738     DWORD bufSize = 0;
2739
2740     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2741     {
2742         /* The NULL form decodes to the decoded member */
2743         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2744          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2745          NULL, (BYTE *)&buf, &bufSize);
2746         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2747         if (buf)
2748         {
2749             comparePublicKeyInfo(&pubKeys[i].decoded,
2750              (CERT_PUBLIC_KEY_INFO *)buf);
2751             LocalFree(buf);
2752         }
2753         /* The non-NULL form decodes to the original */
2754         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2755          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2756          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2757         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2758         if (buf)
2759         {
2760             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2761             LocalFree(buf);
2762         }
2763     }
2764     /* Test with bogus (not valid DER) parameters */
2765     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2766      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2767      NULL, (BYTE *)&buf, &bufSize);
2768     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2769      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2770      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2771      GetLastError());
2772 }
2773
2774 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2775  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2776  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2777  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2778  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2779 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2780  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2781  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2782  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2783  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2784 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2785  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2786  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2787  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2788  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2789 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2790  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2791  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2792  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2793  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2794  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2795  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2796 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2797  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2798  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2799  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2800  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2801  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2802  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2803 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2804  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2805  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2806  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2807  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2808  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2809  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2810  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2811  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2812  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2813 static const BYTE v1CertWithPubKey[] = {
2814 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2815 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2816 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2817 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2818 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2819 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2820 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2821 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2822 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2823 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2824 0x01,0x01 };
2825 static const BYTE v1CertWithPubKeyNoNull[] = {
2826 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2827 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2828 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2829 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2830 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2831 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2832 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2833 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2834 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2835 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2836 static const BYTE v1CertWithSubjectKeyId[] = {
2837 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2838 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2839 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2840 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2841 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2842 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2843 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2844 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2845 0x4c,0x61,0x6e,0x67,0x00 };
2846
2847 static const BYTE serialNum[] = { 0x01 };
2848
2849 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2850 {
2851     BOOL ret;
2852     BYTE *buf = NULL;
2853     DWORD size = 0;
2854     CERT_INFO info = { 0 };
2855     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2856     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2857     CERT_EXTENSION ext;
2858
2859     if (0)
2860     {
2861         /* Test with NULL pvStructInfo (crashes on win9x) */
2862         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2863          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2864         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2865          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2866     }
2867     /* Test with a V1 cert */
2868     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2869      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2870     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2871      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2872     if (buf)
2873     {
2874         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2875          v1Cert[1] + 2, size);
2876         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2877         LocalFree(buf);
2878     }
2879     /* Test v2 cert */
2880     info.dwVersion = CERT_V2;
2881     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2882      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2883     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2884      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2885     if (buf)
2886     {
2887         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2888         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2889         LocalFree(buf);
2890     }
2891     /* Test v3 cert */
2892     info.dwVersion = CERT_V3;
2893     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2894      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2895     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2896      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2897     if (buf)
2898     {
2899         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2900         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2901         LocalFree(buf);
2902     }
2903     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2904      * API doesn't prevent it)
2905      */
2906     info.dwVersion = CERT_V1;
2907     info.cExtension = 1;
2908     info.rgExtension = &criticalExt;
2909     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2910      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2911     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2912      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2913     if (buf)
2914     {
2915         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2916         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2917         LocalFree(buf);
2918     }
2919     /* test v1 cert with a serial number */
2920     info.SerialNumber.cbData = sizeof(serialNum);
2921     info.SerialNumber.pbData = (BYTE *)serialNum;
2922     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2923      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2924     if (buf)
2925     {
2926         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2927         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2928         LocalFree(buf);
2929     }
2930     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2931     info.Issuer.cbData = sizeof(encodedCommonName);
2932     info.Issuer.pbData = (BYTE *)encodedCommonName;
2933     info.Subject.cbData = sizeof(encodedCommonName);
2934     info.Subject.pbData = (BYTE *)encodedCommonName;
2935     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2936      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2937     if (buf)
2938     {
2939         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2940         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2941         LocalFree(buf);
2942     }
2943     /* Add a public key */
2944     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2945     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2946     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2947     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2948      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2949     if (buf)
2950     {
2951         ok(size == sizeof(v1CertWithPubKey) ||
2952          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2953         if (size == sizeof(v1CertWithPubKey))
2954             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2955         else if (size == sizeof(v1CertWithPubKeyNoNull))
2956             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2957              "Got unexpected value\n");
2958         LocalFree(buf);
2959     }
2960     /* Remove the public key, and add a subject key identifier extension */
2961     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2962     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2963     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2964     ext.pszObjId = oid_subject_key_identifier;
2965     ext.fCritical = FALSE;
2966     ext.Value.cbData = sizeof(octetCommonNameValue);
2967     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2968     info.cExtension = 1;
2969     info.rgExtension = &ext;
2970     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2971      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2972     if (buf)
2973     {
2974         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2975         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2976         LocalFree(buf);
2977     }
2978 }
2979
2980 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2981 {
2982     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2983      v1CertWithConstraints, v1CertWithSerial };
2984     BOOL ret;
2985     BYTE *buf = NULL;
2986     DWORD size = 0, i;
2987
2988     /* Test with NULL pbEncoded */
2989     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2990      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2991     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2992      GetLastError() == OSS_BAD_ARG /* Win9x */),
2993      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2994     if (0)
2995     {
2996         /* Crashes on win9x */
2997         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2998          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2999         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3000          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3001     }
3002     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3003      * minimum a cert must have a non-zero serial number, an issuer, and a
3004      * subject.
3005      */
3006     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3007     {
3008         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3009          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3010          (BYTE *)&buf, &size);
3011         ok(!ret, "Expected failure\n");
3012     }
3013     /* Now check with serial number, subject and issuer specified */
3014     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3015      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3016     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3017     if (buf)
3018     {
3019         CERT_INFO *info = (CERT_INFO *)buf;
3020
3021         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3022         ok(info->SerialNumber.cbData == 1,
3023          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3024         ok(*info->SerialNumber.pbData == *serialNum,
3025          "Expected serial number %d, got %d\n", *serialNum,
3026          *info->SerialNumber.pbData);
3027         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3028          "Wrong size %d\n", info->Issuer.cbData);
3029         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3030          "Unexpected issuer\n");
3031         ok(info->Subject.cbData == sizeof(encodedCommonName),
3032          "Wrong size %d\n", info->Subject.cbData);
3033         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3034          info->Subject.cbData), "Unexpected subject\n");
3035         LocalFree(buf);
3036     }
3037     /* Check again with pub key specified */
3038     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3039      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3040      (BYTE *)&buf, &size);
3041     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3042     if (buf)
3043     {
3044         CERT_INFO *info = (CERT_INFO *)buf;
3045
3046         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3047         ok(info->SerialNumber.cbData == 1,
3048          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3049         ok(*info->SerialNumber.pbData == *serialNum,
3050          "Expected serial number %d, got %d\n", *serialNum,
3051          *info->SerialNumber.pbData);
3052         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3053          "Wrong size %d\n", info->Issuer.cbData);
3054         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3055          "Unexpected issuer\n");
3056         ok(info->Subject.cbData == sizeof(encodedCommonName),
3057          "Wrong size %d\n", info->Subject.cbData);
3058         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3059          info->Subject.cbData), "Unexpected subject\n");
3060         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3061          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3062          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3063         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3064          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3065         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3066          sizeof(aKey)), "Unexpected public key\n");
3067         LocalFree(buf);
3068     }
3069 }
3070
3071 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3072  0xe, 0xf };
3073
3074 static const BYTE signedBigCert[] = {
3075  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3076  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3077  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3078  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3079  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3080  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3081  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3082  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3083  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3084  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3085  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3086  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3087
3088 static void test_encodeCert(DWORD dwEncoding)
3089 {
3090     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3091      * also that bigCert is a NULL-terminated string, so don't count its
3092      * last byte (otherwise the signed cert won't decode.)
3093      */
3094     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3095      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3096     BOOL ret;
3097     BYTE *buf = NULL;
3098     DWORD bufSize = 0;
3099
3100     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3101      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3102     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3103     if (buf)
3104     {
3105         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3106         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3107         LocalFree(buf);
3108     }
3109 }
3110
3111 static void test_decodeCert(DWORD dwEncoding)
3112 {
3113     BOOL ret;
3114     BYTE *buf = NULL;
3115     DWORD size = 0;
3116
3117     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3118      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3119     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3120     if (buf)
3121     {
3122         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3123
3124         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3125          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3126         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3127          "Unexpected cert\n");
3128         ok(info->Signature.cbData == sizeof(hash),
3129          "Wrong signature size %d\n", info->Signature.cbData);
3130         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3131          "Unexpected signature\n");
3132         LocalFree(buf);
3133     }
3134     /* A signed cert decodes as a CERT_INFO too */
3135     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3136      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3137     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3138     if (buf)
3139     {
3140         CERT_INFO *info = (CERT_INFO *)buf;
3141
3142         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3143         ok(info->SerialNumber.cbData == 1,
3144          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3145         ok(*info->SerialNumber.pbData == *serialNum,
3146          "Expected serial number %d, got %d\n", *serialNum,
3147          *info->SerialNumber.pbData);
3148         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3149          "Wrong size %d\n", info->Issuer.cbData);
3150         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3151          "Unexpected issuer\n");
3152         ok(info->Subject.cbData == sizeof(encodedCommonName),
3153          "Wrong size %d\n", info->Subject.cbData);
3154         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3155          info->Subject.cbData), "Unexpected subject\n");
3156         LocalFree(buf);
3157     }
3158 }
3159
3160 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3161 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3162  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3163  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3164 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3165  0x00, 0x03 };
3166 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3167  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3168  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3169 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3170  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3171  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3172  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3173  0x2e, 0x6f, 0x72, 0x67 };
3174 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3175  CRL_REASON_AFFILIATION_CHANGED;
3176
3177 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3178 {
3179     CRL_DIST_POINTS_INFO info = { 0 };
3180     CRL_DIST_POINT point = { { 0 } };
3181     CERT_ALT_NAME_ENTRY entry = { 0 };
3182     BOOL ret;
3183     BYTE *buf = NULL;
3184     DWORD size = 0;
3185
3186     /* Test with an empty info */
3187     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3188      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3189     ok(!ret && GetLastError() == E_INVALIDARG,
3190      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3191     /* Test with one empty dist point */
3192     info.cDistPoint = 1;
3193     info.rgDistPoint = &point;
3194     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3195      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3196     if (buf)
3197     {
3198         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3199         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3200         LocalFree(buf);
3201     }
3202     /* A dist point with an invalid name */
3203     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3204     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3205     U(entry).pwszURL = (LPWSTR)nihongoURL;
3206     U(point.DistPointName).FullName.cAltEntry = 1;
3207     U(point.DistPointName).FullName.rgAltEntry = &entry;
3208     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3209      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3210     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3211      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3212     /* The first invalid character is at index 7 */
3213     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3214      "Expected invalid char at index 7, got %d\n",
3215      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3216     /* A dist point with (just) a valid name */
3217     U(entry).pwszURL = (LPWSTR)url;
3218     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3219      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3220     if (buf)
3221     {
3222         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3223         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3224         LocalFree(buf);
3225     }
3226     /* A dist point with (just) reason flags */
3227     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3228     point.ReasonFlags.cbData = sizeof(crlReason);
3229     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3230     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3231      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3232     if (buf)
3233     {
3234         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3235         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3236         LocalFree(buf);
3237     }
3238     /* A dist point with just an issuer */
3239     point.ReasonFlags.cbData = 0;
3240     point.CRLIssuer.cAltEntry = 1;
3241     point.CRLIssuer.rgAltEntry = &entry;
3242     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3243      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3244     if (buf)
3245     {
3246         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3247         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3248         LocalFree(buf);
3249     }
3250     /* A dist point with both a name and an issuer */
3251     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3252     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3253      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3254     if (buf)
3255     {
3256         ok(size == sizeof(distPointWithUrlAndIssuer),
3257          "Wrong size %d\n", size);
3258         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3259         LocalFree(buf);
3260     }
3261 }
3262
3263 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3264 {
3265     BOOL ret;
3266     BYTE *buf = NULL;
3267     DWORD size = 0;
3268     PCRL_DIST_POINTS_INFO info;
3269     PCRL_DIST_POINT point;
3270     PCERT_ALT_NAME_ENTRY entry;
3271
3272     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3273      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3274      (BYTE *)&buf, &size);
3275     if (ret)
3276     {
3277         info = (PCRL_DIST_POINTS_INFO)buf;
3278         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3279          "Wrong size %d\n", size);
3280         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3281          info->cDistPoint);
3282         point = info->rgDistPoint;
3283         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3284          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3285          point->DistPointName.dwDistPointNameChoice);
3286         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3287         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3288         LocalFree(buf);
3289     }
3290     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3291      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3292      (BYTE *)&buf, &size);
3293     if (ret)
3294     {
3295         info = (PCRL_DIST_POINTS_INFO)buf;
3296         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3297          "Wrong size %d\n", size);
3298         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3299          info->cDistPoint);
3300         point = info->rgDistPoint;
3301         ok(point->DistPointName.dwDistPointNameChoice ==
3302          CRL_DIST_POINT_FULL_NAME,
3303          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3304          point->DistPointName.dwDistPointNameChoice);
3305         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3306          "Expected 1 name entry, got %d\n",
3307          U(point->DistPointName).FullName.cAltEntry);
3308         entry = U(point->DistPointName).FullName.rgAltEntry;
3309         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3310          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3311         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3312         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3313         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3314         LocalFree(buf);
3315     }
3316     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3317      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3318      NULL, (BYTE *)&buf, &size);
3319     if (ret)
3320     {
3321         info = (PCRL_DIST_POINTS_INFO)buf;
3322         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3323          "Wrong size %d\n", size);
3324         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3325          info->cDistPoint);
3326         point = info->rgDistPoint;
3327         ok(point->DistPointName.dwDistPointNameChoice ==
3328          CRL_DIST_POINT_NO_NAME,
3329          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3330          point->DistPointName.dwDistPointNameChoice);
3331         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3332          "Expected reason length\n");
3333         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3334          "Unexpected reason\n");
3335         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3336         LocalFree(buf);
3337     }
3338     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3339      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3340      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3341     if (ret)
3342     {
3343         info = (PCRL_DIST_POINTS_INFO)buf;
3344         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3345          "Wrong size %d\n", size);
3346         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3347          info->cDistPoint);
3348         point = info->rgDistPoint;
3349         ok(point->DistPointName.dwDistPointNameChoice ==
3350          CRL_DIST_POINT_FULL_NAME,
3351          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3352          point->DistPointName.dwDistPointNameChoice);
3353         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3354          "Expected 1 name entry, got %d\n",
3355          U(point->DistPointName).FullName.cAltEntry);
3356         entry = U(point->DistPointName).FullName.rgAltEntry;
3357         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3358          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3359         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3360         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3361         ok(point->CRLIssuer.cAltEntry == 1,
3362          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3363         entry = point->CRLIssuer.rgAltEntry;
3364         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3365          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3366         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3367         LocalFree(buf);
3368     }
3369 }
3370
3371 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3372 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3373 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3374  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3375  0x67 };
3376
3377 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3378 {
3379     BOOL ret;
3380     BYTE *buf = NULL;
3381     DWORD size = 0;
3382     CRL_ISSUING_DIST_POINT point = { { 0 } };
3383     CERT_ALT_NAME_ENTRY entry;
3384
3385     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3386      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3387     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3388     {
3389         skip("no X509_ISSUING_DIST_POINT encode support\n");
3390         return;
3391     }
3392     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3393      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3394     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3395      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3396     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3397     if (buf)
3398     {
3399         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3400         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3401         LocalFree(buf);
3402     }
3403     /* nonsensical flags */
3404     point.fOnlyContainsUserCerts = TRUE;
3405     point.fOnlyContainsCACerts = TRUE;
3406     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3407      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3408     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3409     if (buf)
3410     {
3411         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3412         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3413         LocalFree(buf);
3414     }
3415     /* unimplemented name type */
3416     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3417     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3418     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3419      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3420     ok(!ret && GetLastError() == E_INVALIDARG,
3421      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3422     /* empty name */
3423     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3424     U(point.DistPointName).FullName.cAltEntry = 0;
3425     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3426      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3427     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3428     if (buf)
3429     {
3430         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3431         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3432         LocalFree(buf);
3433     }
3434     /* name with URL entry */
3435     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3436     U(entry).pwszURL = (LPWSTR)url;
3437     U(point.DistPointName).FullName.cAltEntry = 1;
3438     U(point.DistPointName).FullName.rgAltEntry = &entry;
3439     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3440      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3441     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3442     if (buf)
3443     {
3444         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3445         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3446         LocalFree(buf);
3447     }
3448 }
3449
3450 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3451  const CERT_ALT_NAME_ENTRY *got)
3452 {
3453     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3454      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3455      got->dwAltNameChoice);
3456     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3457     {
3458         switch (got->dwAltNameChoice)
3459         {
3460         case CERT_ALT_NAME_RFC822_NAME:
3461         case CERT_ALT_NAME_DNS_NAME:
3462         case CERT_ALT_NAME_EDI_PARTY_NAME:
3463         case CERT_ALT_NAME_URL:
3464         case CERT_ALT_NAME_REGISTERED_ID:
3465             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3466              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3467              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3468              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3469              "Unexpected name\n");
3470             break;
3471         case CERT_ALT_NAME_X400_ADDRESS:
3472         case CERT_ALT_NAME_DIRECTORY_NAME:
3473         case CERT_ALT_NAME_IP_ADDRESS:
3474             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3475                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3476             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3477                        U(*got).IPAddress.cbData), "Unexpected value\n");
3478             break;
3479         }
3480     }
3481 }
3482
3483 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3484  const CERT_ALT_NAME_INFO *got)
3485 {
3486     DWORD i;
3487
3488     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3489      expected->cAltEntry, got->cAltEntry);
3490     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3491         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3492 }
3493
3494 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3495  const CRL_DIST_POINT_NAME *got)
3496 {
3497     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3498      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3499     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3500         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3501 }
3502
3503 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3504  const CRL_ISSUING_DIST_POINT *got)
3505 {
3506     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3507     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3508      "Unexpected fOnlyContainsUserCerts\n");
3509     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3510      "Unexpected fOnlyContainsCACerts\n");
3511     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3512      "Unexpected reason flags\n");
3513     ok(got->fIndirectCRL == expected->fIndirectCRL,
3514      "Unexpected fIndirectCRL\n");
3515 }
3516
3517 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3518 {
3519     BOOL ret;
3520     BYTE *buf = NULL;
3521     DWORD size = 0;
3522     CRL_ISSUING_DIST_POINT point = { { 0 } };
3523
3524     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3525      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3526      (BYTE *)&buf, &size);
3527     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3528     {
3529         skip("no X509_ISSUING_DIST_POINT decode support\n");
3530         return;
3531     }
3532     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3533     if (ret)
3534     {
3535         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3536         LocalFree(buf);
3537     }
3538     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3539      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3540      (BYTE *)&buf, &size);
3541     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3542     if (ret)
3543     {
3544         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3545         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3546         LocalFree(buf);
3547     }
3548     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3549      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3550      (BYTE *)&buf, &size);
3551     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3552     if (ret)
3553     {
3554         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3555         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3556         U(point.DistPointName).FullName.cAltEntry = 0;
3557         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3558         LocalFree(buf);
3559     }
3560     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3561      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3562     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3563     if (ret)
3564     {
3565         CERT_ALT_NAME_ENTRY entry;
3566
3567         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3568         U(entry).pwszURL = (LPWSTR)url;
3569         U(point.DistPointName).FullName.cAltEntry = 1;
3570         U(point.DistPointName).FullName.rgAltEntry = &entry;
3571         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3572         LocalFree(buf);
3573     }
3574 }
3575
3576 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3577  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3578  0x30, 0x5a };
3579 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3580  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3581  0x30, 0x30, 0x30, 0x30, 0x5a };
3582 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3583  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3584  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3585  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3586  0x5a };
3587 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3588  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3589  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3590  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3591  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3592  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3593 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3594  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3595  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3596  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3597  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3598  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3599 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3600  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3601  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3602  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3603  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3604  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3605  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3606 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3607  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3608  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3609  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3610  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3611  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3612  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3613 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3614  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3615  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3616  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3617  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3618  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3619  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3620 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3621  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3622  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3623  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3624  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3625  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3626  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3627
3628 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3629 {
3630     BOOL ret;
3631     BYTE *buf = NULL;
3632     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3633     DWORD size = 0;
3634     CRL_INFO info = { 0 };
3635     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3636     CERT_EXTENSION ext;
3637
3638     /* Test with a V1 CRL */
3639     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3640      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3641     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3642      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3643     if (buf)
3644     {
3645         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3646         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3647         LocalFree(buf);
3648     }
3649     /* Test v2 CRL */
3650     info.dwVersion = CRL_V2;
3651     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3652      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3653     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3654      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3655     if (buf)
3656     {
3657         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3658          v2CRL[1] + 2, size);
3659         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3660         LocalFree(buf);
3661     }
3662     /* v1 CRL with a name */
3663     info.dwVersion = CRL_V1;
3664     info.Issuer.cbData = sizeof(encodedCommonName);
3665     info.Issuer.pbData = (BYTE *)encodedCommonName;
3666     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3667      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3668     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3669     if (buf)
3670     {
3671         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3672         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3673         LocalFree(buf);
3674     }
3675     if (0)
3676     {
3677         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3678         info.cCRLEntry = 1;
3679         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3680          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3681         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3682          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3683     }
3684     /* now set an empty entry */
3685     info.cCRLEntry = 1;
3686     info.rgCRLEntry = &entry;
3687     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3688      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3689     if (buf)
3690     {
3691         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3692          "Wrong size %d\n", size);
3693         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3694          "Got unexpected value\n");
3695         LocalFree(buf);
3696     }
3697     /* an entry with a serial number */
3698     entry.SerialNumber.cbData = sizeof(serialNum);
3699     entry.SerialNumber.pbData = (BYTE *)serialNum;
3700     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3701      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3702     if (buf)
3703     {
3704         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3705          "Wrong size %d\n", size);
3706         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3707          "Got unexpected value\n");
3708         LocalFree(buf);
3709     }
3710     /* an entry with an extension */
3711     entry.cExtension = 1;
3712     entry.rgExtension = &criticalExt;
3713     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3714      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3715     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3716     if (buf)
3717     {
3718         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3719         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3720         LocalFree(buf);
3721     }
3722     /* a CRL with an extension */
3723     entry.cExtension = 0;
3724     info.cExtension = 1;
3725     info.rgExtension = &criticalExt;
3726     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3727      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3728     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3729     if (buf)
3730     {
3731         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3732         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3733         LocalFree(buf);
3734     }
3735     /* a v2 CRL with an extension, this time non-critical */
3736     info.dwVersion = CRL_V2;
3737     info.rgExtension = &nonCriticalExt;
3738     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3739      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3740     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3741     if (buf)
3742     {
3743         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3744         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3745         LocalFree(buf);
3746     }
3747     /* a v2 CRL with an issuing dist point extension */
3748     ext.pszObjId = oid_issuing_dist_point;
3749     ext.fCritical = TRUE;
3750     ext.Value.cbData = sizeof(urlIDP);
3751     ext.Value.pbData = (LPBYTE)urlIDP;
3752     entry.rgExtension = &ext;
3753     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3754      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3755     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3756     if (buf)
3757     {
3758         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3759         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3760         LocalFree(buf);
3761     }
3762 }
3763
3764 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3765  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3766  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3767  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3768  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3769  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3770  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3771  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3772  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3773  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3774  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3775  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3776  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3777  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3778  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3779  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3780  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3781  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3782  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3783  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3784  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3785  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3786  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3787  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3788  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3789  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3790  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3791  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3792  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3793  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3794  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3795  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3796  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3797  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3798  0xcd };
3799 static const BYTE verisignCRLWithLotsOfEntries[] = {
3800 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3801 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3802 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3803 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3804 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3805 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3806 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3807 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3808 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3809 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3810 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3811 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3812 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3813 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3814 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3815 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3816 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3817 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3818 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3819 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3820 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3821 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3822 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3823 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3824 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3825 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3826 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3827 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3828 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3829 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3830 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3831 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3832 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3833 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3834 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3835 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3836 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3837 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3838 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3839 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3840 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3841 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3842 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3843 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3844 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3845 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3846 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3847 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3848 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3849 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3850 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3851 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3852 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3853 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3854 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3855 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3856 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3857 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3858 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3859 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3860 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3861 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3862 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3863 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3864 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3865 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3866 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3867 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3868 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3869 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3870 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3871 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3872 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3873 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3874 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3875 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3876 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3877 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3878 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3879 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3880 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3881 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3882 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3883 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3884 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3885 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3886 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3887 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3888 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3889 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3890 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3891 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3892 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3893 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3894 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3895 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3896 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3897 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3898 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3899 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3900 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3901 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3902 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3903 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3904 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3905 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3906 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3907 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3908 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3909 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3910 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3911 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3912 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3913 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3914 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3915 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3916 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3917 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3918 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3919 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3920 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3921 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3922 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3923 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3924 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3925 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3926 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3927 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3928 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3929 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3930 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3931 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3932 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3933 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3934 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3935 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3936 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3937 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3938 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3939 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3940 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3941 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3942 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3943 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3944 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3945 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3946 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3947 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3948 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3949 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3950 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3951 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3952 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3953 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3954 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3955 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3956 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3957 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3958 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3959 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3960 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3961 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3962 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3963 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3964 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3965 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3966 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3967 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3968 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3969 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3970 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3971 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3972 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3973 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3974 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3975 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3976 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3977 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3978 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3979 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3980 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3981 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3982 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3983 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3984 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3985 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3986 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3987 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3988 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3989 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3990 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3991 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3992 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3993 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3994 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3995 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3996 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3997 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3998 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3999 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4000 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4001 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4002 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4003 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4004 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4005 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4006 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4007 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4008 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4009 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4010 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4011 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4012 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4013 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4014 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4015 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4016 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4017 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4018 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4019 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4020 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4021 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4022 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4023 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4024 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4025 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4026 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4027 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4028 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4029 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4030 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4031 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4032 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4033 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4034 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4035 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4036 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4037 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4038 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4039 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4040 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4041 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4042 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4043 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4044 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4045 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4046 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4047 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4048 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4049 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4050 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4051 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4052 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4053 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4054 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4055 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4056 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4057 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4058 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4059 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4060 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4061 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4062 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4063 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4064 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4065 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4066 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4067 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4068 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4069 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4070 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4071 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4072 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4073 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4074 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4075 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4076 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4077 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4078 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4079 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4080 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4081 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4082 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4083 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4084 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4085 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4086 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4087 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4088 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4089 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4090 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4091 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4092 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4093 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4094 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4095 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4096 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4097 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4098 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4099 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4100 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4101 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4102 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4103 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4104 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4105 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4106 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4107 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4108 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4109 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4110 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4111 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4112 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4113 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4114 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4115 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4116 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4117 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4118 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4119 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4120 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4121 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4122 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4123 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4124 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4125 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4126 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4127 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4128 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4129 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4130 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4131 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4132 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4133 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4134 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4135 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4136 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4137 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4138 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4139 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4140 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4141 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4142 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4143 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4144 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4145 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4146 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4147 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4148 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4149 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4150 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4151 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4152 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4153 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4154 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4155 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4156 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4157 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4158 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4159 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4160 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4161 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4162 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4163 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4164 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4165 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4166 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4167 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4168 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4169 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4170 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4171 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4172 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4173 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4174 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4175 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4176 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4177 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4178 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4179 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4180 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4181 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4182 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4183 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4184 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4185 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4186 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4187 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4188 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4189 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4190 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4191 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4192 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4193 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4194 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4195 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4196 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4197 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4198 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4199 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4200 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4201 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4202 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4203 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4204 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4205 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4206 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4207 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4208 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4209 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4210 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4211 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4212 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4213 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4214 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4215 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4216 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4217 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4218 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4219 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4220 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4221 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4222 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4223 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4224 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4225 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4226 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4227 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4228 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4229 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4230 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4231 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4232 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4233 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4234 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4235 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4236 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4237 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4238 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4239 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4240 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4241 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4242 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4243 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4244 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4245 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4246 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4247 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4248 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4249 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4250 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4251 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4252 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4253 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4254 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4255 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4256 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4257 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4258 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4259 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4260 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4261 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4262 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4263 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4264 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4265 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4266 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4267 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4268 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4269 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4270 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4271 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4272 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4273 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4274 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4275 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4276 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4277 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4278 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4279 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4280 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4281 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4282 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4283 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4284 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4285 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4286 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4287 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4288 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4289 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4290 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4291 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4292 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4293 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4294 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4295 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4296 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4297 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4298 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4299 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4300 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4301 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4302 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4303 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4304 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4305 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4306 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4307 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4308
4309 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4310 {
4311     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4312     BOOL ret;
4313     BYTE *buf = NULL;
4314     DWORD size = 0, i;
4315
4316     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4317     {
4318         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4319          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4320          (BYTE *)&buf, &size);
4321         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4322          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4323          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4324          GetLastError());
4325     }
4326     /* at a minimum, a CRL must contain an issuer: */
4327     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4328      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4329      (BYTE *)&buf, &size);
4330     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4331     if (buf)
4332     {
4333         CRL_INFO *info = (CRL_INFO *)buf;
4334
4335         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4336         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4337          info->cCRLEntry);
4338         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4339          "Wrong issuer size %d\n", info->Issuer.cbData);
4340         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4341          "Unexpected issuer\n");
4342         LocalFree(buf);
4343     }
4344     /* check decoding with an empty CRL entry */
4345     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4346      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4347      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4348     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4349      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4350      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4351      GetLastError());
4352     /* with a real CRL entry */
4353     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4354      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4355      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4356     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4357     if (buf)
4358     {
4359         CRL_INFO *info = (CRL_INFO *)buf;
4360         CRL_ENTRY *entry;
4361
4362         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4363         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4364          info->cCRLEntry);
4365         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4366         entry = info->rgCRLEntry;
4367         ok(entry->SerialNumber.cbData == 1,
4368          "Expected serial number size 1, got %d\n",
4369          entry->SerialNumber.cbData);
4370         ok(*entry->SerialNumber.pbData == *serialNum,
4371          "Expected serial number %d, got %d\n", *serialNum,
4372          *entry->SerialNumber.pbData);
4373         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4374          "Wrong issuer size %d\n", info->Issuer.cbData);
4375         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4376          "Unexpected issuer\n");
4377         LocalFree(buf);
4378     }
4379     /* a real CRL from verisign that has extensions */
4380     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4381      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4382      NULL, (BYTE *)&buf, &size);
4383     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4384     if (buf)
4385     {
4386         CRL_INFO *info = (CRL_INFO *)buf;
4387         CRL_ENTRY *entry;
4388
4389         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4390         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4391          info->cCRLEntry);
4392         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4393         entry = info->rgCRLEntry;
4394         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4395          info->cExtension);
4396         LocalFree(buf);
4397     }
4398     /* another real CRL from verisign that has lots of entries */
4399     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4400      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4401      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4402     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4403     if (buf)
4404     {
4405         CRL_INFO *info = (CRL_INFO *)buf;
4406
4407         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4408         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4409          info->cCRLEntry);
4410         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4411          info->cExtension);
4412         LocalFree(buf);
4413     }
4414     /* and finally, with an extension */
4415     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4416      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4417      NULL, (BYTE *)&buf, &size);
4418     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4419     if (buf)
4420     {
4421         CRL_INFO *info = (CRL_INFO *)buf;
4422         CRL_ENTRY *entry;
4423
4424         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4425         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4426          info->cCRLEntry);
4427         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4428         entry = info->rgCRLEntry;
4429         ok(entry->SerialNumber.cbData == 1,
4430          "Expected serial number size 1, got %d\n",
4431          entry->SerialNumber.cbData);
4432         ok(*entry->SerialNumber.pbData == *serialNum,
4433          "Expected serial number %d, got %d\n", *serialNum,
4434          *entry->SerialNumber.pbData);
4435         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4436          "Wrong issuer size %d\n", info->Issuer.cbData);
4437         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4438          "Unexpected issuer\n");
4439         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4440          info->cExtension);
4441         LocalFree(buf);
4442     }
4443     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4444      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4445      NULL, (BYTE *)&buf, &size);
4446     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4447     if (buf)
4448     {
4449         CRL_INFO *info = (CRL_INFO *)buf;
4450
4451         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4452          info->cExtension);
4453         LocalFree(buf);
4454     }
4455     /* And again, with an issuing dist point */
4456     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4457      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4458      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4459     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4460     if (buf)
4461     {
4462         CRL_INFO *info = (CRL_INFO *)buf;
4463
4464         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4465          info->cExtension);
4466         LocalFree(buf);
4467     }
4468 }
4469
4470 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4471  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4472 static const BYTE encodedUsage[] = {
4473  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4474  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4475  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4476
4477 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4478 {
4479     BOOL ret;
4480     BYTE *buf = NULL;
4481     DWORD size = 0;
4482     CERT_ENHKEY_USAGE usage;
4483
4484     /* Test with empty usage */
4485     usage.cUsageIdentifier = 0;
4486     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4487      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4488     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4489     if (buf)
4490     {
4491         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4492         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4493         LocalFree(buf);
4494     }
4495     /* Test with a few usages */
4496     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4497     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4498     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4499      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4500     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4501     if (buf)
4502     {
4503         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4504         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4505         LocalFree(buf);
4506     }
4507 }
4508
4509 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4510 {
4511     BOOL ret;
4512     LPBYTE buf = NULL;
4513     DWORD size = 0;
4514
4515     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4516      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4517      (BYTE *)&buf, &size);
4518     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4519     if (buf)
4520     {
4521         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4522
4523         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4524          "Wrong size %d\n", size);
4525         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4526          usage->cUsageIdentifier);
4527         LocalFree(buf);
4528     }
4529     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4530      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4531      (BYTE *)&buf, &size);
4532     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4533     if (buf)
4534     {
4535         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4536         DWORD i;
4537
4538         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4539          "Wrong size %d\n", size);
4540         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4541          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4542         for (i = 0; i < usage->cUsageIdentifier; i++)
4543             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4544              "Expected OID %s, got %s\n", keyUsages[i],
4545              usage->rgpszUsageIdentifier[i]);
4546         LocalFree(buf);
4547     }
4548 }
4549
4550 static BYTE keyId[] = { 1,2,3,4 };
4551 static const BYTE authorityKeyIdWithId[] = {
4552  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4553 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4554  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4555  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4556 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4557
4558 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4559 {
4560     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4561     BOOL ret;
4562     BYTE *buf = NULL;
4563     DWORD size = 0;
4564
4565     /* Test with empty id */
4566     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4567      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4568     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4569     if (buf)
4570     {
4571         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4572         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4573         LocalFree(buf);
4574     }
4575     /* With just a key id */
4576     info.KeyId.cbData = sizeof(keyId);
4577     info.KeyId.pbData = keyId;
4578     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4579      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4580     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4581     if (buf)
4582     {
4583         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4584         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4585         LocalFree(buf);
4586     }
4587     /* With just an issuer */
4588     info.KeyId.cbData = 0;
4589     info.CertIssuer.cbData = sizeof(encodedCommonName);
4590     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4591     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4592      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4593     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4594     if (buf)
4595     {
4596         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4597          size);
4598         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4599         LocalFree(buf);
4600     }
4601     /* With just a serial number */
4602     info.CertIssuer.cbData = 0;
4603     info.CertSerialNumber.cbData = sizeof(serialNum);
4604     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4605     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4606      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4607     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4608     if (buf)
4609     {
4610         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4611          size);
4612         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4613         LocalFree(buf);
4614     }
4615 }
4616
4617 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4618 {
4619     BOOL ret;
4620     LPBYTE buf = NULL;
4621     DWORD size = 0;
4622
4623     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4624      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4625      (BYTE *)&buf, &size);
4626     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4627     if (buf)
4628     {
4629         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4630
4631         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4632          size);
4633         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4634         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4635         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4636         LocalFree(buf);
4637     }
4638     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4639      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4640      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4641     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4642     if (buf)
4643     {
4644         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4645
4646         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4647          size);
4648         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4649         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4650          "Unexpected key id\n");
4651         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4652         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4653         LocalFree(buf);
4654     }
4655     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4656      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4657      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4658     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4659     if (buf)
4660     {
4661         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4662
4663         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4664          size);
4665         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4666         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4667          "Unexpected issuer len\n");
4668         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4669          sizeof(encodedCommonName)), "Unexpected issuer\n");
4670         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4671         LocalFree(buf);
4672     }
4673     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4674      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4675      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4676     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4677     if (buf)
4678     {
4679         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4680
4681         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4682          size);
4683         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4684         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4685         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4686          "Unexpected serial number len\n");
4687         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4688          "Unexpected serial number\n");
4689         LocalFree(buf);
4690     }
4691 }
4692
4693 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4694  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4695  0x6f,0x72,0x67 };
4696
4697 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4698 {
4699     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4700     CERT_ALT_NAME_ENTRY entry = { 0 };
4701     BOOL ret;
4702     BYTE *buf = NULL;
4703     DWORD size = 0;
4704
4705     /* Test with empty id */
4706     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4707      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4708     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4709     if (buf)
4710     {
4711         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4712         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4713         LocalFree(buf);
4714     }
4715     /* With just a key id */
4716     info.KeyId.cbData = sizeof(keyId);
4717     info.KeyId.pbData = keyId;
4718     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4719      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4720     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4721     if (buf)
4722     {
4723         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4724          size);
4725         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4726         LocalFree(buf);
4727     }
4728     /* With a bogus issuer name */
4729     info.KeyId.cbData = 0;
4730     info.AuthorityCertIssuer.cAltEntry = 1;
4731     info.AuthorityCertIssuer.rgAltEntry = &entry;
4732     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4733      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4734     ok(!ret && GetLastError() == E_INVALIDARG,
4735      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4736     /* With an issuer name */
4737     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4738     U(entry).pwszURL = (LPWSTR)url;
4739     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4740      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4741     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4742     if (buf)
4743     {
4744         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4745          size);
4746         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4747          "Unexpected value\n");
4748         LocalFree(buf);
4749     }
4750     /* With just a serial number */
4751     info.AuthorityCertIssuer.cAltEntry = 0;
4752     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4753     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4754     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4755      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4756     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4757     if (buf)
4758     {
4759         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4760          size);
4761         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4762         LocalFree(buf);
4763     }
4764 }
4765
4766 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4767 {
4768     BOOL ret;
4769     LPBYTE buf = NULL;
4770     DWORD size = 0;
4771
4772     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4773      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4774      (BYTE *)&buf, &size);
4775     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4776     if (buf)
4777     {
4778         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4779
4780         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4781          size);
4782         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4783         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4784          "Expected no issuer name entries\n");
4785         ok(info->AuthorityCertSerialNumber.cbData == 0,
4786          "Expected no serial number\n");
4787         LocalFree(buf);
4788     }
4789     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4790      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4791      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4792     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4793     if (buf)
4794     {
4795         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4796
4797         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4798          size);
4799         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4800         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4801          "Unexpected key id\n");
4802         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4803          "Expected no issuer name entries\n");
4804         ok(info->AuthorityCertSerialNumber.cbData == 0,
4805          "Expected no serial number\n");
4806         LocalFree(buf);
4807     }
4808     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4809      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4810      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4811     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4812     if (buf)
4813     {
4814         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4815
4816         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4817          size);
4818         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4819         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4820          "Expected 1 issuer entry, got %d\n",
4821          info->AuthorityCertIssuer.cAltEntry);
4822         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4823          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4824          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4825         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4826          url), "Unexpected URL\n");
4827         ok(info->AuthorityCertSerialNumber.cbData == 0,
4828          "Expected no serial number\n");
4829         LocalFree(buf);
4830     }
4831     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4832      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4833      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4834     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4835     if (buf)
4836     {
4837         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4838
4839         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4840          size);
4841         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4842         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4843          "Expected no issuer name entries\n");
4844         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4845          "Unexpected serial number len\n");
4846         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4847          sizeof(serialNum)), "Unexpected serial number\n");
4848         LocalFree(buf);
4849     }
4850 }
4851
4852 static const BYTE authorityInfoAccessWithUrl[] = {
4853 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4854 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4855 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4856 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4857 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4858 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4859
4860 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4861 {
4862     static char oid1[] = "1.2.3";
4863     static char oid2[] = "1.5.6";
4864     BOOL ret;
4865     BYTE *buf = NULL;
4866     DWORD size = 0;
4867     CERT_ACCESS_DESCRIPTION accessDescription[2];
4868     CERT_AUTHORITY_INFO_ACCESS aia;
4869
4870     memset(accessDescription, 0, sizeof(accessDescription));
4871     aia.cAccDescr = 0;
4872     aia.rgAccDescr = NULL;
4873     /* Having no access descriptions is allowed */
4874     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4875      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4876     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4877     if (buf)
4878     {
4879         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4880         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4881         LocalFree(buf);
4882         buf = NULL;
4883     }
4884     /* It can't have an empty access method */
4885     aia.cAccDescr = 1;
4886     aia.rgAccDescr = accessDescription;
4887     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4888      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4889     ok(!ret && (GetLastError() == E_INVALIDARG ||
4890      GetLastError() == OSS_LIMITED /* Win9x */),
4891      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4892     /* It can't have an empty location */
4893     accessDescription[0].pszAccessMethod = oid1;
4894     SetLastError(0xdeadbeef);
4895     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4896      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4897     ok(!ret && GetLastError() == E_INVALIDARG,
4898      "expected E_INVALIDARG, got %08x\n", GetLastError());
4899     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4900     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4901     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4902      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4903     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4904     if (buf)
4905     {
4906         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4907          size);
4908         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4909          "unexpected value\n");
4910         LocalFree(buf);
4911         buf = NULL;
4912     }
4913     accessDescription[1].pszAccessMethod = oid2;
4914     accessDescription[1].AccessLocation.dwAltNameChoice =
4915      CERT_ALT_NAME_IP_ADDRESS;
4916     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4917      sizeof(encodedIPAddr);
4918     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4919      (LPBYTE)encodedIPAddr;
4920     aia.cAccDescr = 2;
4921     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4922      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4923     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4924     if (buf)
4925     {
4926         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4927          "unexpected size %d\n", size);
4928         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4929          "unexpected value\n");
4930         LocalFree(buf);
4931         buf = NULL;
4932     }
4933 }
4934
4935 static void compareAuthorityInfoAccess(LPCSTR header,
4936  const CERT_AUTHORITY_INFO_ACCESS *expected,
4937  const CERT_AUTHORITY_INFO_ACCESS *got)
4938 {
4939     DWORD i;
4940
4941     ok(expected->cAccDescr == got->cAccDescr,
4942      "%s: expected %d access descriptions, got %d\n", header,
4943      expected->cAccDescr, got->cAccDescr);
4944     for (i = 0; i < expected->cAccDescr; i++)
4945     {
4946         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4947          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4948          header, i, expected->rgAccDescr[i].pszAccessMethod,
4949          got->rgAccDescr[i].pszAccessMethod);
4950         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4951          &got->rgAccDescr[i].AccessLocation);
4952     }
4953 }
4954
4955 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4956 {
4957     static char oid1[] = "1.2.3";
4958     static char oid2[] = "1.5.6";
4959     BOOL ret;
4960     LPBYTE buf = NULL;
4961     DWORD size = 0;
4962
4963     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4964      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4965      (BYTE *)&buf, &size);
4966     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4967     if (buf)
4968     {
4969         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4970
4971         compareAuthorityInfoAccess("empty AIA", &aia,
4972          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4973         LocalFree(buf);
4974         buf = NULL;
4975     }
4976     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4977      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4978      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4979     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4980     if (buf)
4981     {
4982         CERT_ACCESS_DESCRIPTION accessDescription;
4983         CERT_AUTHORITY_INFO_ACCESS aia;
4984
4985         accessDescription.pszAccessMethod = oid1;
4986         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4987         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
4988         aia.cAccDescr = 1;
4989         aia.rgAccDescr = &accessDescription;
4990         compareAuthorityInfoAccess("AIA with URL", &aia,
4991          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4992         LocalFree(buf);
4993         buf = NULL;
4994     }
4995     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4996      authorityInfoAccessWithUrlAndIPAddr,
4997      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
4998      NULL, (BYTE *)&buf, &size);
4999     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5000     if (buf)
5001     {
5002         CERT_ACCESS_DESCRIPTION accessDescription[2];
5003         CERT_AUTHORITY_INFO_ACCESS aia;
5004
5005         accessDescription[0].pszAccessMethod = oid1;
5006         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5007         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5008         accessDescription[1].pszAccessMethod = oid2;
5009         accessDescription[1].AccessLocation.dwAltNameChoice =
5010          CERT_ALT_NAME_IP_ADDRESS;
5011         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5012          sizeof(encodedIPAddr);
5013         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5014          (LPBYTE)encodedIPAddr;
5015         aia.cAccDescr = 2;
5016         aia.rgAccDescr = accessDescription;
5017         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5018          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5019         LocalFree(buf);
5020         buf = NULL;
5021     }
5022 }
5023
5024 static const BYTE emptyCTL[] = {
5025 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5026 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5027 static const BYTE emptyCTLWithVersion1[] = {
5028 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5029 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5030 static const BYTE ctlWithUsageIdentifier[] = {
5031 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5032 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5033 static const BYTE ctlWithListIdentifier[] = {
5034 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5035 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5036 static const BYTE ctlWithSequenceNumber[] = {
5037 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5038 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5039 static const BYTE ctlWithThisUpdate[] = {
5040 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5041 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5042 static const BYTE ctlWithThisAndNextUpdate[] = {
5043 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5044 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5045 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5046 static const BYTE ctlWithAlgId[] = {
5047 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5048 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5049 static const BYTE ctlWithBogusEntry[] = {
5050 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5051 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5052 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5053 static const BYTE ctlWithOneEntry[] = {
5054 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5055 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5056 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5057 static const BYTE ctlWithTwoEntries[] = {
5058 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5059 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5060 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5061 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5062 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5063
5064 static void test_encodeCTL(DWORD dwEncoding)
5065 {
5066     static char oid1[] = "1.2.3";
5067     static char oid2[] = "1.5.6";
5068     char *pOid1 = oid1;
5069     BOOL ret;
5070     BYTE *buf = NULL;
5071     DWORD size = 0;
5072     CTL_INFO info;
5073     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5074     CTL_ENTRY ctlEntry[2];
5075     CRYPT_ATTRIBUTE attr1, attr2;
5076     CRYPT_ATTR_BLOB value1, value2;
5077
5078     memset(&info, 0, sizeof(info));
5079     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5080      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5081     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5082     if (buf)
5083     {
5084         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5085         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5086         LocalFree(buf);
5087         buf = NULL;
5088     }
5089     info.dwVersion = 1;
5090     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5091      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5092     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5093     if (buf)
5094     {
5095         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5096         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5097         LocalFree(buf);
5098         buf = NULL;
5099     }
5100     info.dwVersion = 0;
5101     info.SubjectUsage.cUsageIdentifier = 1;
5102     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5103     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5104      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5106     if (buf)
5107     {
5108         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5109          size);
5110         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5111         LocalFree(buf);
5112         buf = NULL;
5113     }
5114     info.SubjectUsage.cUsageIdentifier = 0;
5115     info.ListIdentifier.cbData = sizeof(serialNum);
5116     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5117     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5118      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5119     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5120     if (buf)
5121     {
5122         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5123         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5124         LocalFree(buf);
5125         buf = NULL;
5126     }
5127     info.ListIdentifier.cbData = 0;
5128     info.SequenceNumber.cbData = sizeof(serialNum);
5129     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5130     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5131      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5132     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5133     if (buf)
5134     {
5135         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5136          size);
5137         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5138         LocalFree(buf);
5139         buf = NULL;
5140     }
5141     info.SequenceNumber.cbData = 0;
5142     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5143     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5144      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5145     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5146     if (buf)
5147     {
5148         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5149         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5150         LocalFree(buf);
5151         buf = NULL;
5152     }
5153     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5154     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5155      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5156     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5157     if (buf)
5158     {
5159         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5160          size);
5161         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5162         LocalFree(buf);
5163         buf = NULL;
5164     }
5165     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5166     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5167     info.SubjectAlgorithm.pszObjId = oid2;
5168     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5169      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5170     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5171     if (buf)
5172     {
5173         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5174         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5175         LocalFree(buf);
5176         buf = NULL;
5177     }
5178     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5179      * (see tests below) but it'll encode fine.
5180      */
5181     info.SubjectAlgorithm.pszObjId = NULL;
5182     value1.cbData = sizeof(serialNum);
5183     value1.pbData = (LPBYTE)serialNum;
5184     attr1.pszObjId = oid1;
5185     attr1.cValue = 1;
5186     attr1.rgValue = &value1;
5187     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5188     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5189     ctlEntry[0].cAttribute = 1;
5190     ctlEntry[0].rgAttribute = &attr1;
5191     info.cCTLEntry = 1;
5192     info.rgCTLEntry = ctlEntry;
5193     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5194      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5195     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5196     if (buf)
5197     {
5198         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5199         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5200         LocalFree(buf);
5201         buf = NULL;
5202     }
5203     value1.cbData = sizeof(emptySequence);
5204     value1.pbData = (LPBYTE)emptySequence;
5205     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5206      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5207     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5208     if (buf)
5209     {
5210         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5211         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5212         LocalFree(buf);
5213         buf = NULL;
5214     }
5215     value2.cbData = sizeof(encodedIPAddr);
5216     value2.pbData = (LPBYTE)encodedIPAddr;
5217     attr2.pszObjId = oid2;
5218     attr2.cValue = 1;
5219     attr2.rgValue = &value2;
5220     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5221     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5222     ctlEntry[1].cAttribute = 1;
5223     ctlEntry[1].rgAttribute = &attr2;
5224     info.cCTLEntry = 2;
5225     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5226      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5227     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5228     if (buf)
5229     {
5230         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5231         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5232         LocalFree(buf);
5233         buf = NULL;
5234     }
5235 }
5236
5237 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5238  const CTL_INFO *got)
5239 {
5240     DWORD i, j, k;
5241
5242     ok(expected->dwVersion == got->dwVersion,
5243      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5244      got->dwVersion);
5245     ok(expected->SubjectUsage.cUsageIdentifier ==
5246      got->SubjectUsage.cUsageIdentifier,
5247      "%s: expected %d usage identifiers, got %d\n", header,
5248      expected->SubjectUsage.cUsageIdentifier,
5249      got->SubjectUsage.cUsageIdentifier);
5250     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5251         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5252          got->SubjectUsage.rgpszUsageIdentifier[i]),
5253          "%s[%d]: expected %s, got %s\n", header, i,
5254          expected->SubjectUsage.rgpszUsageIdentifier[i],
5255          got->SubjectUsage.rgpszUsageIdentifier[i]);
5256     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5257      "%s: expected list identifier of %d bytes, got %d\n", header,
5258      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5259     if (expected->ListIdentifier.cbData)
5260         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5261          expected->ListIdentifier.cbData),
5262          "%s: unexpected list identifier value\n", header);
5263     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5264      "%s: expected sequence number of %d bytes, got %d\n", header,
5265      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5266     if (expected->SequenceNumber.cbData)
5267         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5268          expected->SequenceNumber.cbData),
5269          "%s: unexpected sequence number value\n", header);
5270     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5271      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5272      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5273      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5274     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5275      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5276      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5277      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5278     if (expected->SubjectAlgorithm.pszObjId &&
5279      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5280         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5281          expected->SubjectAlgorithm.pszObjId);
5282     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5283         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5284          got->SubjectAlgorithm.pszObjId),
5285          "%s: expected subject algorithm %s, got %s\n", header,
5286          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5287     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5288      got->SubjectAlgorithm.Parameters.cbData,
5289      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5290      expected->SubjectAlgorithm.Parameters.cbData,
5291      got->SubjectAlgorithm.Parameters.cbData);
5292     if (expected->SubjectAlgorithm.Parameters.cbData)
5293         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5294          got->SubjectAlgorithm.Parameters.pbData,
5295          expected->SubjectAlgorithm.Parameters.cbData),
5296          "%s: unexpected subject algorithm parameter value\n", header);
5297     ok(expected->cCTLEntry == got->cCTLEntry,
5298      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5299      got->cCTLEntry);
5300     for (i = 0; i < expected->cCTLEntry; i++)
5301     {
5302         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5303          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5304          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5305          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5306          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5307         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5308             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5309              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5310              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5311              "%s[%d]: unexpected subject identifier value\n",
5312              header, i);
5313         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5314         {
5315             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5316              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5317              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5318              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5319              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5320             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5321             {
5322                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5323                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5324                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5325                  header, i, j, k,
5326                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5327                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5328                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5329                     ok(!memcmp(
5330                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5331                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5332                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5333                      "%s[%d][%d][%d]: unexpected value\n",
5334                      header, i, j, k);
5335             }
5336         }
5337     }
5338     ok(expected->cExtension == got->cExtension,
5339      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5340      got->cExtension);
5341     for (i = 0; i < expected->cExtension; i++)
5342     {
5343         ok(!strcmp(expected->rgExtension[i].pszObjId,
5344          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5345          header, i, expected->rgExtension[i].pszObjId,
5346          got->rgExtension[i].pszObjId);
5347         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5348          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5349          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5350         ok(expected->rgExtension[i].Value.cbData ==
5351          got->rgExtension[i].Value.cbData,
5352          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5353          header, i, expected->rgExtension[i].Value.cbData,
5354          got->rgExtension[i].Value.cbData);
5355         if (expected->rgExtension[i].Value.cbData)
5356             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5357              got->rgExtension[i].Value.pbData,
5358              expected->rgExtension[i].Value.cbData),
5359              "%s[%d]: unexpected extension value\n", header, i);
5360     }
5361 }
5362
5363 static const BYTE signedCTL[] = {
5364 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5365 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5366 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5367 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5368 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5369 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5370 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5371 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5372 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5373 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5374 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5375 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5376 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5377 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5378 static const BYTE signedCTLWithCTLInnerContent[] = {
5379 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5380 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5381 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5382 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5383 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5384 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5385 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5386 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5387 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5388 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5389 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5390 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5391 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5392 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5393 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5394 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5395 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5396 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5397 0x57,0x6c,0x0b,0x47,0xb8 };
5398
5399 static void test_decodeCTL(DWORD dwEncoding)
5400 {
5401     static char oid1[] = "1.2.3";
5402     static char oid2[] = "1.5.6";
5403     static BYTE nullData[] = { 5,0 };
5404     char *pOid1 = oid1;
5405     BOOL ret;
5406     BYTE *buf = NULL;
5407     DWORD size = 0;
5408     CTL_INFO info;
5409     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5410     CTL_ENTRY ctlEntry[2];
5411     CRYPT_ATTRIBUTE attr1, attr2;
5412     CRYPT_ATTR_BLOB value1, value2;
5413
5414     memset(&info, 0, sizeof(info));
5415     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5416      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5417     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5418     if (buf)
5419     {
5420         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5421         LocalFree(buf);
5422         buf = NULL;
5423     }
5424     info.dwVersion = 1;
5425     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5426      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5427      &size);
5428     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5429     if (buf)
5430     {
5431         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5432         LocalFree(buf);
5433         buf = NULL;
5434     }
5435     info.dwVersion = 0;
5436     info.SubjectUsage.cUsageIdentifier = 1;
5437     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5438     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5439      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5440      (BYTE *)&buf, &size);
5441     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5442     if (buf)
5443     {
5444         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5445         LocalFree(buf);
5446         buf = NULL;
5447     }
5448     info.SubjectUsage.cUsageIdentifier = 0;
5449     info.ListIdentifier.cbData = sizeof(serialNum);
5450     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5451     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5452      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5453      (BYTE *)&buf, &size);
5454     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5455     if (buf)
5456     {
5457         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5458         LocalFree(buf);
5459         buf = NULL;
5460     }
5461     info.ListIdentifier.cbData = 0;
5462     info.SequenceNumber.cbData = sizeof(serialNum);
5463     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5464     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5465      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5466      (BYTE *)&buf, &size);
5467     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5468     if (buf)
5469     {
5470         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5471         LocalFree(buf);
5472         buf = NULL;
5473     }
5474     info.SequenceNumber.cbData = 0;
5475     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5476     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5477      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5478      (BYTE *)&buf, &size);
5479     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5480     if (buf)
5481     {
5482         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5483         LocalFree(buf);
5484         buf = NULL;
5485     }
5486     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5487     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5488      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5489      (BYTE *)&buf, &size);
5490     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5491     if (buf)
5492     {
5493         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5494         LocalFree(buf);
5495         buf = NULL;
5496     }
5497     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5498     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5499     info.SubjectAlgorithm.pszObjId = oid2;
5500     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5501     info.SubjectAlgorithm.Parameters.pbData = nullData;
5502     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5503      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5504      (BYTE *)&buf, &size);
5505     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5506     if (buf)
5507     {
5508         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5509         LocalFree(buf);
5510         buf = NULL;
5511     }
5512     SetLastError(0xdeadbeef);
5513     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5514      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5515      (BYTE *)&buf, &size);
5516     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5517      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5518      GetLastError());
5519     info.SubjectAlgorithm.Parameters.cbData = 0;
5520     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5521     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5522     info.SubjectAlgorithm.pszObjId = oid2;
5523     info.SubjectAlgorithm.pszObjId = NULL;
5524     value1.cbData = sizeof(emptySequence);
5525     value1.pbData = (LPBYTE)emptySequence;
5526     attr1.pszObjId = oid1;
5527     attr1.cValue = 1;
5528     attr1.rgValue = &value1;
5529     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5530     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5531     ctlEntry[0].cAttribute = 1;
5532     ctlEntry[0].rgAttribute = &attr1;
5533     info.cCTLEntry = 1;
5534     info.rgCTLEntry = ctlEntry;
5535     SetLastError(0xdeadbeef);
5536     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5537      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5538      (BYTE *)&buf, &size);
5539     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5540     if (buf)
5541     {
5542         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5543         LocalFree(buf);
5544         buf = NULL;
5545     }
5546     value2.cbData = sizeof(encodedIPAddr);
5547     value2.pbData = (LPBYTE)encodedIPAddr;
5548     attr2.pszObjId = oid2;
5549     attr2.cValue = 1;
5550     attr2.rgValue = &value2;
5551     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5552     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5553     ctlEntry[1].cAttribute = 1;
5554     ctlEntry[1].rgAttribute = &attr2;
5555     info.cCTLEntry = 2;
5556     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5557      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5558      (BYTE *)&buf, &size);
5559     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5560     if (buf)
5561     {
5562         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5563         LocalFree(buf);
5564         buf = NULL;
5565     }
5566     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5567     SetLastError(0xdeadbeef);
5568     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5569      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5570     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5571      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5572      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5573      GetLastError());
5574     SetLastError(0xdeadbeef);
5575     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5576      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5577      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5578     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5579      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5580      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5581      GetLastError());
5582 }
5583
5584 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5585 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5586  0x03,0,0,0,0,0,0 };
5587 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5588  0xa0,0x01,0x01 };
5589 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5590  0x03,0x02,0x01,0x01 };
5591 static BYTE bogusDER[] = { 1 };
5592
5593 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5594 {
5595     BOOL ret;
5596     BYTE *buf = NULL;
5597     DWORD size = 0;
5598     CRYPT_CONTENT_INFO info = { 0 };
5599     char oid1[] = "1.2.3";
5600
5601     if (0)
5602     {
5603         /* Crashes on win9x */
5604         SetLastError(0xdeadbeef);
5605         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5606          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5607         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5608          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5609     }
5610     SetLastError(0xdeadbeef);
5611     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5612      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5613     ok(!ret && (GetLastError() == E_INVALIDARG ||
5614      GetLastError() == OSS_LIMITED /* Win9x */),
5615      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5616     info.pszObjId = oid1;
5617     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5618      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5619     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5620     if (buf)
5621     {
5622         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5623         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5624         LocalFree(buf);
5625     }
5626     info.Content.pbData = bogusDER;
5627     info.Content.cbData = sizeof(bogusDER);
5628     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5629      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5630     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5631     if (buf)
5632     {
5633         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5634         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5635         LocalFree(buf);
5636     }
5637     info.Content.pbData = (BYTE *)ints[0].encoded;
5638     info.Content.cbData = ints[0].encoded[1] + 2;
5639     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5640      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5641     if (buf)
5642     {
5643         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5644         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5645         LocalFree(buf);
5646     }
5647 }
5648
5649 static const BYTE indefiniteSignedPKCSContent[] = {
5650 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5651 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5652 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5653 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5654 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5655 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5656 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5657 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5658 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5659 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5660 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5661 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5662 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5663 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5664 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5665 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5666 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5667 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5668 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5669 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5670 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5671 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5672 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5673 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5674 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5675 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5676 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5677 0x00,0x00,0x00,0x00,0x00,0x00 };
5678
5679 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5680 {
5681     BOOL ret;
5682     LPBYTE buf = NULL;
5683     DWORD size = 0;
5684     CRYPT_CONTENT_INFO *info;
5685
5686     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5687      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5688      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5689     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5690     if (buf)
5691     {
5692         info = (CRYPT_CONTENT_INFO *)buf;
5693
5694         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5695          info->pszObjId);
5696         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5697          info->Content.cbData);
5698         LocalFree(buf);
5699     }
5700     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5701      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5702      0, NULL, NULL, &size);
5703     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5704     SetLastError(0xdeadbeef);
5705     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5706      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5707      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5708     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5709      * I doubt an app depends on that.
5710      */
5711     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5712      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5713      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5714      GetLastError());
5715     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5716      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5717      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5718     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5719     if (buf)
5720     {
5721         info = (CRYPT_CONTENT_INFO *)buf;
5722
5723         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5724          info->pszObjId);
5725         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5726          "Unexpected size %d\n", info->Content.cbData);
5727         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5728          info->Content.cbData), "Unexpected value\n");
5729         LocalFree(buf);
5730     }
5731     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5732      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5733      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5734     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5735     if (buf)
5736     {
5737         info = (CRYPT_CONTENT_INFO *)buf;
5738
5739         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5740          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5741         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5742          info->Content.cbData);
5743         LocalFree(buf);
5744     }
5745 }
5746
5747 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5748  0x00 };
5749 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5750  0x01 };
5751 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5752  0x02,0x01,0x01 };
5753
5754 static void test_encodePKCSAttribute(DWORD dwEncoding)
5755 {
5756     CRYPT_ATTRIBUTE attr = { 0 };
5757     BOOL ret;
5758     LPBYTE buf = NULL;
5759     DWORD size = 0;
5760     CRYPT_ATTR_BLOB blob;
5761     char oid[] = "1.2.3";
5762
5763     if (0)
5764     {
5765         /* Crashes on win9x */
5766         SetLastError(0xdeadbeef);
5767         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5768          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5769         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5770          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5771     }
5772     SetLastError(0xdeadbeef);
5773     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5774      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5775     ok(!ret && (GetLastError() == E_INVALIDARG ||
5776      GetLastError() == OSS_LIMITED /* Win9x */),
5777      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5778     attr.pszObjId = oid;
5779     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5780      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5781     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5782     if (buf)
5783     {
5784         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5785         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5786         LocalFree(buf);
5787     }
5788     blob.cbData = sizeof(bogusDER);
5789     blob.pbData = bogusDER;
5790     attr.cValue = 1;
5791     attr.rgValue = &blob;
5792     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5793      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5794     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5795     if (buf)
5796     {
5797         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5798         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5799         LocalFree(buf);
5800     }
5801     blob.pbData = (BYTE *)ints[0].encoded;
5802     blob.cbData = ints[0].encoded[1] + 2;
5803     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5804      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5805     if (buf)
5806     {
5807         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5808         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5809         LocalFree(buf);
5810     }
5811 }
5812
5813 static void test_decodePKCSAttribute(DWORD dwEncoding)
5814 {
5815     BOOL ret;
5816     LPBYTE buf = NULL;
5817     DWORD size = 0;
5818     CRYPT_ATTRIBUTE *attr;
5819
5820     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5821      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5822      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5823     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5824     if (buf)
5825     {
5826         attr = (CRYPT_ATTRIBUTE *)buf;
5827
5828         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5829          attr->pszObjId);
5830         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5831         LocalFree(buf);
5832     }
5833     SetLastError(0xdeadbeef);
5834     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5835      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5836      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5837     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5838      * I doubt an app depends on that.
5839      */
5840     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5841      GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */),
5842      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5843      GetLastError());
5844     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5845      intPKCSAttr, sizeof(intPKCSAttr),
5846      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5847     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5848     if (buf)
5849     {
5850         attr = (CRYPT_ATTRIBUTE *)buf;
5851
5852         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5853          attr->pszObjId);
5854         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5855         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5856          "Unexpected size %d\n", attr->rgValue[0].cbData);
5857         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5858          attr->rgValue[0].cbData), "Unexpected value\n");
5859         LocalFree(buf);
5860     }
5861 }
5862
5863 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5864 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5865  0x2a,0x03,0x31,0x00 };
5866 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5867  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5868
5869 static void test_encodePKCSAttributes(DWORD dwEncoding)
5870 {
5871     CRYPT_ATTRIBUTES attributes = { 0 };
5872     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5873     CRYPT_ATTR_BLOB blob;
5874     BOOL ret;
5875     LPBYTE buf = NULL;
5876     DWORD size = 0;
5877     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5878
5879     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5880      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5881     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5882     if (buf)
5883     {
5884         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5885         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5886         LocalFree(buf);
5887     }
5888     attributes.cAttr = 1;
5889     attributes.rgAttr = attr;
5890     SetLastError(0xdeadbeef);
5891     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5892      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5893     ok(!ret && (GetLastError() == E_INVALIDARG ||
5894      GetLastError() == OSS_LIMITED /* Win9x */),
5895      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5896     attr[0].pszObjId = oid1;
5897     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5898      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5899     if (buf)
5900     {
5901         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5902         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5903         LocalFree(buf);
5904     }
5905     attr[1].pszObjId = oid2;
5906     attr[1].cValue = 1;
5907     attr[1].rgValue = &blob;
5908     blob.pbData = (BYTE *)ints[0].encoded;
5909     blob.cbData = ints[0].encoded[1] + 2;
5910     attributes.cAttr = 2;
5911     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5912      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5913     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5914     if (buf)
5915     {
5916         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5917         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5918         LocalFree(buf);
5919     }
5920 }
5921
5922 static void test_decodePKCSAttributes(DWORD dwEncoding)
5923 {
5924     BOOL ret;
5925     LPBYTE buf = NULL;
5926     DWORD size = 0;
5927     CRYPT_ATTRIBUTES *attributes;
5928
5929     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5930      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5931      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5932     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5933     if (buf)
5934     {
5935         attributes = (CRYPT_ATTRIBUTES *)buf;
5936         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5937          attributes->cAttr);
5938         LocalFree(buf);
5939     }
5940     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5941      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5942      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5943     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5944     if (buf)
5945     {
5946         attributes = (CRYPT_ATTRIBUTES *)buf;
5947         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5948          attributes->cAttr);
5949         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5950          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5951         ok(attributes->rgAttr[0].cValue == 0,
5952          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5953         LocalFree(buf);
5954     }
5955     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5956      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5957      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5958     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5959     if (buf)
5960     {
5961         attributes = (CRYPT_ATTRIBUTES *)buf;
5962         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5963          attributes->cAttr);
5964         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5965          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5966         ok(attributes->rgAttr[0].cValue == 0,
5967          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5968         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5969          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5970         ok(attributes->rgAttr[1].cValue == 1,
5971          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5972         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5973          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5974         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5975          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5976         LocalFree(buf);
5977     }
5978 }
5979
5980 static const BYTE singleCapability[] = {
5981 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5982 static const BYTE twoCapabilities[] = {
5983 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5984 static const BYTE singleCapabilitywithNULL[] = {
5985 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5986
5987 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5988 {
5989     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5990     BOOL ret;
5991     LPBYTE buf = NULL;
5992     DWORD size = 0;
5993     CRYPT_SMIME_CAPABILITY capability[2];
5994     CRYPT_SMIME_CAPABILITIES capabilities;
5995
5996     /* An empty capabilities is allowed */
5997     capabilities.cCapability = 0;
5998     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5999      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6000     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6001     if (buf)
6002     {
6003         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6004         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6005         LocalFree(buf);
6006     }
6007     /* A non-empty capabilities with an empty capability (lacking an OID) is
6008      * not allowed
6009      */
6010     capability[0].pszObjId = NULL;
6011     capability[0].Parameters.cbData = 0;
6012     capabilities.cCapability = 1;
6013     capabilities.rgCapability = capability;
6014     SetLastError(0xdeadbeef);
6015     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6016      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6017     ok(!ret && (GetLastError() == E_INVALIDARG ||
6018      GetLastError() == OSS_LIMITED /* Win9x */),
6019      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6020     capability[0].pszObjId = oid1;
6021     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6022      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6023     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6024     if (buf)
6025     {
6026         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6027         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6028         LocalFree(buf);
6029     }
6030     capability[1].pszObjId = oid2;
6031     capability[1].Parameters.cbData = 0;
6032     capabilities.cCapability = 2;
6033     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6034      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6035     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6036     if (buf)
6037     {
6038         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6039         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6040         LocalFree(buf);
6041     }
6042 }
6043
6044 static void compareSMimeCapabilities(LPCSTR header,
6045  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6046 {
6047     DWORD i;
6048
6049     ok(got->cCapability == expected->cCapability,
6050      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6051      got->cCapability);
6052     for (i = 0; i < expected->cCapability; i++)
6053     {
6054         ok(!strcmp(expected->rgCapability[i].pszObjId,
6055          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6056          header, i, expected->rgCapability[i].pszObjId,
6057          got->rgCapability[i].pszObjId);
6058         ok(expected->rgCapability[i].Parameters.cbData ==
6059          got->rgCapability[i].Parameters.cbData,
6060          "%s[%d]: expected %d bytes, got %d\n", header, i,
6061          expected->rgCapability[i].Parameters.cbData,
6062          got->rgCapability[i].Parameters.cbData);
6063         if (expected->rgCapability[i].Parameters.cbData)
6064             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6065              got->rgCapability[i].Parameters.pbData,
6066              expected->rgCapability[i].Parameters.cbData),
6067              "%s[%d]: unexpected value\n", header, i);
6068     }
6069 }
6070
6071 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6072 {
6073     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6074     BOOL ret;
6075     DWORD size = 0;
6076     CRYPT_SMIME_CAPABILITY capability[2];
6077     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6078
6079     SetLastError(0xdeadbeef);
6080     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6081      emptySequence, sizeof(emptySequence),
6082      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6083     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6084     if (ret)
6085     {
6086         capabilities.cCapability = 0;
6087         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6088         LocalFree(ptr);
6089     }
6090     SetLastError(0xdeadbeef);
6091     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6092      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6093      (BYTE *)&ptr, &size);
6094     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6095     if (ret)
6096     {
6097         capability[0].pszObjId = oid1;
6098         capability[0].Parameters.cbData = 0;
6099         capabilities.cCapability = 1;
6100         capabilities.rgCapability = capability;
6101         compareSMimeCapabilities("single capability", &capabilities, ptr);
6102         LocalFree(ptr);
6103     }
6104     SetLastError(0xdeadbeef);
6105     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6106      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6107      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6108     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6109     if (ret)
6110     {
6111         BYTE NULLparam[] = {0x05, 0x00};
6112         capability[0].pszObjId = oid1;
6113         capability[0].Parameters.cbData = 2;
6114         capability[0].Parameters.pbData = NULLparam;
6115         capabilities.cCapability = 1;
6116         capabilities.rgCapability = capability;
6117         compareSMimeCapabilities("single capability with NULL", &capabilities,
6118          ptr);
6119         LocalFree(ptr);
6120     }
6121     SetLastError(0xdeadbeef);
6122     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6123     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6124     (BYTE *)&ptr, &size);
6125     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6126     if (ret)
6127     {
6128         capability[0].Parameters.cbData = 0;
6129         capability[1].pszObjId = oid2;
6130         capability[1].Parameters.cbData = 0;
6131         capabilities.cCapability = 2;
6132         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6133         LocalFree(ptr);
6134     }
6135 }
6136
6137 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6138  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6139  0x67 };
6140 static const BYTE minimalPKCSSigner[] = {
6141  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6142  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6143  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6144 static const BYTE PKCSSignerWithSerial[] = {
6145  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6146  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6147  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6148  0x00 };
6149 static const BYTE PKCSSignerWithHashAlgo[] = {
6150  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6151  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6152  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6153  0x00,0x04,0x00 };
6154 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6155  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6156  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6157  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6158  0x06,0x05,0x00,0x04,0x00 };
6159 static const BYTE PKCSSignerWithHash[] = {
6160  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6161  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6162  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6163  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6164  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6165 static const BYTE PKCSSignerWithAuthAttr[] = {
6166 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6167 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6168 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6169 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6170 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6171 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6172 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6173
6174 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6175 {
6176     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6177     BOOL ret;
6178     LPBYTE buf = NULL;
6179     DWORD size = 0;
6180     CMSG_SIGNER_INFO info = { 0 };
6181     char oid_common_name[] = szOID_COMMON_NAME;
6182     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6183      (LPBYTE)encodedCommonName };
6184     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6185
6186     SetLastError(0xdeadbeef);
6187     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6188      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6189     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6190     {
6191         skip("no PKCS7_SIGNER_INFO encode support\n");
6192         return;
6193     }
6194     ok(!ret && (GetLastError() == E_INVALIDARG ||
6195      GetLastError() == OSS_LIMITED /* Win9x */),
6196      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6197     /* To be encoded, a signer must have an issuer at least, and the encoding
6198      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6199      * see decoding tests.)
6200      */
6201     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6202     info.Issuer.pbData = encodedCommonNameNoNull;
6203     SetLastError(0xdeadbeef);
6204     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6205      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6206     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6207         ok(!ret && GetLastError() == E_INVALIDARG,
6208          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6209     else
6210     {
6211         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6212          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6213         if (buf)
6214         {
6215             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6216             if (size == sizeof(minimalPKCSSigner))
6217                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6218             else
6219                 ok(0, "Unexpected value\n");
6220             LocalFree(buf);
6221         }
6222     }
6223     info.SerialNumber.cbData = sizeof(serialNum);
6224     info.SerialNumber.pbData = (BYTE *)serialNum;
6225     SetLastError(0xdeadbeef);
6226     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6227      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6228     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6229         ok(!ret && GetLastError() == E_INVALIDARG,
6230          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6231     else
6232     {
6233         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6234          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6235         if (buf)
6236         {
6237             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6238              size);
6239             if (size == sizeof(PKCSSignerWithSerial))
6240                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6241                  "Unexpected value\n");
6242             else
6243                 ok(0, "Unexpected value\n");
6244             LocalFree(buf);
6245         }
6246     }
6247     info.HashAlgorithm.pszObjId = oid1;
6248     SetLastError(0xdeadbeef);
6249     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6250      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6251     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6252         ok(!ret && GetLastError() == E_INVALIDARG,
6253          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6254     else
6255     {
6256         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6257          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6258         if (buf)
6259         {
6260             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6261              size);
6262             if (size == sizeof(PKCSSignerWithHashAlgo))
6263                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6264                  "Unexpected value\n");
6265             else
6266                 ok(0, "Unexpected value\n");
6267             LocalFree(buf);
6268         }
6269     }
6270     info.HashEncryptionAlgorithm.pszObjId = oid2;
6271     SetLastError(0xdeadbeef);
6272     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6273      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6274     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6275         ok(!ret && GetLastError() == E_INVALIDARG,
6276          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6277     else
6278     {
6279         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6280         if (buf)
6281         {
6282             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6283              "Unexpected size %d\n", size);
6284             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6285                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6286                  "Unexpected value\n");
6287             else
6288                 ok(0, "Unexpected value\n");
6289             LocalFree(buf);
6290         }
6291     }
6292     info.EncryptedHash.cbData = sizeof(hash);
6293     info.EncryptedHash.pbData = (BYTE *)hash;
6294     SetLastError(0xdeadbeef);
6295     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6296      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6297     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6298         ok(!ret && GetLastError() == E_INVALIDARG,
6299          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6300     else
6301     {
6302         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6303         if (buf)
6304         {
6305             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6306              size);
6307             if (size == sizeof(PKCSSignerWithHash))
6308                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6309                  "Unexpected value\n");
6310             else
6311                 ok(0, "Unexpected value\n");
6312             LocalFree(buf);
6313         }
6314     }
6315     info.AuthAttrs.cAttr = 1;
6316     info.AuthAttrs.rgAttr = &attr;
6317     SetLastError(0xdeadbeef);
6318     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6319      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6320     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6321         ok(!ret && GetLastError() == E_INVALIDARG,
6322          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6323     else
6324     {
6325         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6326         if (buf)
6327         {
6328             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6329              size);
6330             if (size == sizeof(PKCSSignerWithAuthAttr))
6331                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6332                  "Unexpected value\n");
6333             else
6334                 ok(0, "Unexpected value\n");
6335             LocalFree(buf);
6336         }
6337     }
6338 }
6339
6340 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6341 {
6342     BOOL ret;
6343     LPBYTE buf = NULL;
6344     DWORD size = 0;
6345     CMSG_SIGNER_INFO *info;
6346
6347     /* A PKCS signer can't be decoded without a serial number. */
6348     SetLastError(0xdeadbeef);
6349     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6350      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6351      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6352     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6353      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6354      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6355      GetLastError());
6356     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6357      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6358      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6359     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6360      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6361     if (buf)
6362     {
6363         info = (CMSG_SIGNER_INFO *)buf;
6364         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6365          info->dwVersion);
6366         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6367          "Unexpected size %d\n", info->Issuer.cbData);
6368         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6369          info->Issuer.cbData), "Unexpected value\n");
6370         ok(info->SerialNumber.cbData == sizeof(serialNum),
6371          "Unexpected size %d\n", info->SerialNumber.cbData);
6372         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6373          "Unexpected value\n");
6374         LocalFree(buf);
6375     }
6376     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6377      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6378      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6379     if (buf)
6380     {
6381         info = (CMSG_SIGNER_INFO *)buf;
6382         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6383          info->dwVersion);
6384         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6385          "Unexpected size %d\n", info->Issuer.cbData);
6386         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6387          info->Issuer.cbData), "Unexpected value\n");
6388         ok(info->SerialNumber.cbData == sizeof(serialNum),
6389          "Unexpected size %d\n", info->SerialNumber.cbData);
6390         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6391          "Unexpected value\n");
6392         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6393          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6394         LocalFree(buf);
6395     }
6396     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6397      PKCSSignerWithHashAndEncryptionAlgo,
6398      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6399      NULL, (BYTE *)&buf, &size);
6400     if (buf)
6401     {
6402         info = (CMSG_SIGNER_INFO *)buf;
6403         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6404          info->dwVersion);
6405         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6406          "Unexpected size %d\n", info->Issuer.cbData);
6407         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6408          info->Issuer.cbData), "Unexpected value\n");
6409         ok(info->SerialNumber.cbData == sizeof(serialNum),
6410          "Unexpected size %d\n", info->SerialNumber.cbData);
6411         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6412          "Unexpected value\n");
6413         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6414          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6415         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6416          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6417         LocalFree(buf);
6418     }
6419     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6420      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6421      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6422     if (buf)
6423     {
6424         info = (CMSG_SIGNER_INFO *)buf;
6425         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6426          info->dwVersion);
6427         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6428          "Unexpected size %d\n", info->Issuer.cbData);
6429         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6430          info->Issuer.cbData), "Unexpected value\n");
6431         ok(info->SerialNumber.cbData == sizeof(serialNum),
6432          "Unexpected size %d\n", info->SerialNumber.cbData);
6433         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6434          "Unexpected value\n");
6435         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6436          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6437         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6438          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6439         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6440          info->EncryptedHash.cbData);
6441         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6442          "Unexpected value\n");
6443         LocalFree(buf);
6444     }
6445     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6446      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6447      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6448     if (buf)
6449     {
6450         info = (CMSG_SIGNER_INFO *)buf;
6451         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6452          info->AuthAttrs.cAttr);
6453         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6454          "Expected %s, got %s\n", szOID_COMMON_NAME,
6455          info->AuthAttrs.rgAttr[0].pszObjId);
6456         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6457          info->AuthAttrs.rgAttr[0].cValue);
6458         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6459          sizeof(encodedCommonName), "Unexpected size %d\n",
6460          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6461         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6462          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6463         LocalFree(buf);
6464     }
6465 }
6466
6467 static const BYTE CMSSignerWithKeyId[] = {
6468 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6469 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6470
6471 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6472 {
6473     BOOL ret;
6474     LPBYTE buf = NULL;
6475     DWORD size = 0;
6476     CMSG_CMS_SIGNER_INFO info = { 0 };
6477     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6478
6479     SetLastError(0xdeadbeef);
6480     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6481      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6482     ok(!ret, "Expected failure, got %d\n", ret);
6483     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6484     {
6485         skip("no CMS_SIGNER_INFO encode support\n");
6486         return;
6487     }
6488     ok(GetLastError() == E_INVALIDARG,
6489        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6490     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6491     SetLastError(0xdeadbeef);
6492     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6493      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6494     ok(!ret, "Expected failure, got %d\n", ret);
6495     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6496     {
6497         skip("no CMS_SIGNER_INFO encode support\n");
6498         return;
6499     }
6500     ok(GetLastError() == E_INVALIDARG,
6501        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6502     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6503      * be a key id or a issuer serial number with at least the issuer set, and
6504      * the encoding must include PKCS_7_ASN_ENCODING.
6505      * (That isn't enough to be decoded, see decoding tests.)
6506      */
6507     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6508      sizeof(encodedCommonNameNoNull);
6509     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6510     SetLastError(0xdeadbeef);
6511     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6512      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6513     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6514         ok(!ret && GetLastError() == E_INVALIDARG,
6515          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6516     else
6517     {
6518         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6519         if (buf)
6520         {
6521             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6522             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6523             LocalFree(buf);
6524         }
6525     }
6526     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6527     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6528     SetLastError(0xdeadbeef);
6529     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6530      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6531     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6532         ok(!ret && GetLastError() == E_INVALIDARG,
6533          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6534     else
6535     {
6536         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6537         if (buf)
6538         {
6539             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6540              size);
6541             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6542             LocalFree(buf);
6543         }
6544     }
6545     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6546     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6547     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6548     SetLastError(0xdeadbeef);
6549     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6550      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6551     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6552         ok(!ret && GetLastError() == E_INVALIDARG,
6553          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6554     else
6555     {
6556         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6557         if (buf)
6558         {
6559             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6560              size);
6561             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6562             LocalFree(buf);
6563         }
6564     }
6565     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6566      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6567      * (see RFC 3852, section 5.3.)
6568      */
6569     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6570     U(info.SignerId).HashId.cbData = sizeof(hash);
6571     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6572     SetLastError(0xdeadbeef);
6573     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6574      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6575     ok(!ret && GetLastError() == E_INVALIDARG,
6576      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6577     /* Now with a hash algo */
6578     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6579     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6580      sizeof(encodedCommonNameNoNull);
6581     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6582     info.HashAlgorithm.pszObjId = oid1;
6583     SetLastError(0xdeadbeef);
6584     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6585      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6586     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6587         ok(!ret && GetLastError() == E_INVALIDARG,
6588          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6589     else
6590     {
6591         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6592         if (buf)
6593         {
6594             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6595              size);
6596             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6597              "Unexpected value\n");
6598             LocalFree(buf);
6599         }
6600     }
6601     info.HashEncryptionAlgorithm.pszObjId = oid2;
6602     SetLastError(0xdeadbeef);
6603     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6604      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6605     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6606         ok(!ret && GetLastError() == E_INVALIDARG,
6607          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6608     else
6609     {
6610         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6611         if (buf)
6612         {
6613             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6614              "Unexpected size %d\n", size);
6615             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6616              "Unexpected value\n");
6617             LocalFree(buf);
6618         }
6619     }
6620     info.EncryptedHash.cbData = sizeof(hash);
6621     info.EncryptedHash.pbData = (BYTE *)hash;
6622     SetLastError(0xdeadbeef);
6623     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6624      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6625     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6626         ok(!ret && GetLastError() == E_INVALIDARG,
6627          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6628     else
6629     {
6630         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6631         if (buf)
6632         {
6633             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6634              size);
6635             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6636             LocalFree(buf);
6637         }
6638     }
6639 }
6640
6641 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6642 {
6643     BOOL ret;
6644     LPBYTE buf = NULL;
6645     DWORD size = 0;
6646     CMSG_CMS_SIGNER_INFO *info;
6647     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6648
6649     /* A CMS signer can't be decoded without a serial number. */
6650     SetLastError(0xdeadbeef);
6651     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6652      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6653      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6654     ok(!ret, "expected failure\n");
6655     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6656     {
6657         skip("no CMS_SIGNER_INFO decode support\n");
6658         return;
6659     }
6660     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6661      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6662     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6663      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6664      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6665     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6666     if (buf)
6667     {
6668         info = (CMSG_CMS_SIGNER_INFO *)buf;
6669         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6670          info->dwVersion);
6671         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6672          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6673          info->SignerId.dwIdChoice);
6674         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6675          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6676          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6677         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6678          encodedCommonNameNoNull,
6679          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6680          "Unexpected value\n");
6681         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6682          sizeof(serialNum), "Unexpected size %d\n",
6683          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6684         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6685          serialNum, sizeof(serialNum)), "Unexpected value\n");
6686         LocalFree(buf);
6687     }
6688     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6689      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6690      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6691     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6692     if (buf)
6693     {
6694         info = (CMSG_CMS_SIGNER_INFO *)buf;
6695         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6696          info->dwVersion);
6697         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6698          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6699          info->SignerId.dwIdChoice);
6700         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6701          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6702          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6703         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6704          encodedCommonNameNoNull,
6705          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6706          "Unexpected value\n");
6707         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6708          sizeof(serialNum), "Unexpected size %d\n",
6709          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6710         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6711          serialNum, sizeof(serialNum)), "Unexpected value\n");
6712         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6713          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6714         LocalFree(buf);
6715     }
6716     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6717      PKCSSignerWithHashAndEncryptionAlgo,
6718      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6719      NULL, (BYTE *)&buf, &size);
6720     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6721     if (buf)
6722     {
6723         info = (CMSG_CMS_SIGNER_INFO *)buf;
6724         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6725          info->dwVersion);
6726         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6727          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6728          info->SignerId.dwIdChoice);
6729         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6730          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6731          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6732         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6733          encodedCommonNameNoNull,
6734          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6735          "Unexpected value\n");
6736         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6737          sizeof(serialNum), "Unexpected size %d\n",
6738          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6739         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6740          serialNum, sizeof(serialNum)), "Unexpected value\n");
6741         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6742          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6743         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6744          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6745         LocalFree(buf);
6746     }
6747     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6748      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6749      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6750     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6751     if (buf)
6752     {
6753         info = (CMSG_CMS_SIGNER_INFO *)buf;
6754         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6755          info->dwVersion);
6756         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6757          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6758          info->SignerId.dwIdChoice);
6759         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6760          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6761          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6762         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6763          encodedCommonNameNoNull,
6764          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6765          "Unexpected value\n");
6766         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6767          sizeof(serialNum), "Unexpected size %d\n",
6768          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6769         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6770          serialNum, sizeof(serialNum)), "Unexpected value\n");
6771         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6772          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6773         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6774          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6775         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6776          info->EncryptedHash.cbData);
6777         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6778          "Unexpected value\n");
6779         LocalFree(buf);
6780     }
6781     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6782      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6783      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6784     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6785     if (buf)
6786     {
6787         info = (CMSG_CMS_SIGNER_INFO *)buf;
6788         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6789          info->dwVersion);
6790         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6791          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6792          info->SignerId.dwIdChoice);
6793         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6794          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6795         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6796          "Unexpected value\n");
6797         LocalFree(buf);
6798     }
6799 }
6800
6801 static BYTE emptyDNSPermittedConstraints[] = {
6802 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6803 static BYTE emptyDNSExcludedConstraints[] = {
6804 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6805 static BYTE DNSExcludedConstraints[] = {
6806 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6807 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6808 static BYTE permittedAndExcludedConstraints[] = {
6809 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6810 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6811 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6812 static BYTE permittedAndExcludedWithMinConstraints[] = {
6813 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6814 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6815 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6816 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6817 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6818 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6819 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6820
6821 static void test_encodeNameConstraints(DWORD dwEncoding)
6822 {
6823     BOOL ret;
6824     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6825     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6826     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6827     LPBYTE buf;
6828     DWORD size;
6829
6830     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6831      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6832     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6833     {
6834         skip("no X509_NAME_CONSTRAINTS encode support\n");
6835         return;
6836     }
6837     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6838     if (ret)
6839     {
6840         ok(size == sizeof(emptySequence), "Unexpected size\n");
6841         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6842         LocalFree(buf);
6843     }
6844     constraints.cPermittedSubtree = 1;
6845     constraints.rgPermittedSubtree = &permitted;
6846     SetLastError(0xdeadbeef);
6847     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6848      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6849     ok(!ret && GetLastError() == E_INVALIDARG,
6850      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6851     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6852     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6853      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6854     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6855     if (ret)
6856     {
6857         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6858         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6859          "Unexpected value\n");
6860         LocalFree(buf);
6861     }
6862     constraints.cPermittedSubtree = 0;
6863     constraints.cExcludedSubtree = 1;
6864     constraints.rgExcludedSubtree = &excluded;
6865     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6866     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6867      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6868     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6869     if (ret)
6870     {
6871         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6872         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6873          "Unexpected value\n");
6874         LocalFree(buf);
6875     }
6876     U(excluded.Base).pwszURL = (LPWSTR)url;
6877     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6878      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6879     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6880     if (ret)
6881     {
6882         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6883         ok(!memcmp(buf, DNSExcludedConstraints, size),
6884          "Unexpected value\n");
6885         LocalFree(buf);
6886     }
6887     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6888     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6889     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6890     constraints.cPermittedSubtree = 1;
6891     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6892      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6893     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6894     if (ret)
6895     {
6896         ok(size == sizeof(permittedAndExcludedConstraints),
6897          "Unexpected size\n");
6898         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6899          "Unexpected value\n");
6900         LocalFree(buf);
6901     }
6902     permitted.dwMinimum = 5;
6903     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6904      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6905     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6906     if (ret)
6907     {
6908         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6909          "Unexpected size\n");
6910         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6911          "Unexpected value\n");
6912         LocalFree(buf);
6913     }
6914     permitted.fMaximum = TRUE;
6915     permitted.dwMaximum = 3;
6916     SetLastError(0xdeadbeef);
6917     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6918      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6919     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6920     if (ret)
6921     {
6922         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6923          "Unexpected size\n");
6924         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6925          "Unexpected value\n");
6926         LocalFree(buf);
6927     }
6928 }
6929
6930 struct EncodedNameConstraints
6931 {
6932     CRYPT_DATA_BLOB            encoded;
6933     CERT_NAME_CONSTRAINTS_INFO constraints;
6934 };
6935
6936 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6937  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6938 static CERT_GENERAL_SUBTREE DNSSubtree = {
6939  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6940 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6941  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6942 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6943  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6944 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6945  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6946
6947 struct EncodedNameConstraints encodedNameConstraints[] = {
6948  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6949  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6950    { 1, &emptyDNSSubtree, 0, NULL } },
6951  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6952    { 0, NULL, 1, &emptyDNSSubtree } },
6953  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6954    { 0, NULL, 1, &DNSSubtree } },
6955  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6956    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6957  { { sizeof(permittedAndExcludedWithMinConstraints),
6958      permittedAndExcludedWithMinConstraints },
6959    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6960  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6961      permittedAndExcludedWithMinMaxConstraints },
6962    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6963 };
6964
6965 static void test_decodeNameConstraints(DWORD dwEncoding)
6966 {
6967     BOOL ret;
6968     DWORD i;
6969     CERT_NAME_CONSTRAINTS_INFO *constraints;
6970
6971     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6972     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6973     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6974     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6975     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6976     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6977     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6978     for (i = 0;
6979      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6980      i++)
6981     {
6982         DWORD size;
6983
6984         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6985          encodedNameConstraints[i].encoded.pbData,
6986          encodedNameConstraints[i].encoded.cbData,
6987          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6988         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6989         {
6990             skip("no X509_NAME_CONSTRAINTS decode support\n");
6991             return;
6992         }
6993         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6994         if (ret)
6995         {
6996             DWORD j;
6997
6998             if (constraints->cPermittedSubtree !=
6999              encodedNameConstraints[i].constraints.cPermittedSubtree)
7000                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7001                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7002                  constraints->cPermittedSubtree);
7003             if (constraints->cPermittedSubtree ==
7004              encodedNameConstraints[i].constraints.cPermittedSubtree)
7005             {
7006                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7007                 {
7008                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7009                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7010                 }
7011             }
7012             if (constraints->cExcludedSubtree !=
7013              encodedNameConstraints[i].constraints.cExcludedSubtree)
7014                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7015                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7016                  constraints->cExcludedSubtree);
7017             if (constraints->cExcludedSubtree ==
7018              encodedNameConstraints[i].constraints.cExcludedSubtree)
7019             {
7020                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7021                 {
7022                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7023                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7024                 }
7025             }
7026             LocalFree(constraints);
7027         }
7028     }
7029 }
7030
7031 /* Free *pInfo with HeapFree */
7032 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7033 {
7034     BOOL ret;
7035     DWORD size = 0;
7036     HCRYPTKEY key;
7037
7038     /* This crashes
7039     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7040      */
7041     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7042     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7043      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7044     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7045      &size);
7046     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7047      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7048     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7049      NULL, &size);
7050     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7051      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7052     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7053      0, NULL, NULL, &size);
7054     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7055      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7056     /* Test with no key */
7057     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7058      0, NULL, NULL, &size);
7059     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7060      GetLastError());
7061     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7062     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7063     if (ret)
7064     {
7065         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7066          NULL, 0, NULL, NULL, &size);
7067         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7068         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7069         if (*pInfo)
7070         {
7071             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7072              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7073             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7074              GetLastError());
7075             if (ret)
7076             {
7077                 /* By default (we passed NULL as the OID) the OID is
7078                  * szOID_RSA_RSA.
7079                  */
7080                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7081                  "Expected %s, got %s\n", szOID_RSA_RSA,
7082                  (*pInfo)->Algorithm.pszObjId);
7083             }
7084         }
7085     }
7086     CryptDestroyKey(key);
7087 }
7088
7089 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7090  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7091  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7092  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7093  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7094  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7095  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7096  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7097  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7098  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7099  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7100  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7101  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7102  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7103  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7104  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7105  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7106  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7107  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7108  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7109  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7110  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7111  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7112  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7113  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7114
7115 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7116 {
7117     BOOL ret;
7118     HCRYPTKEY key;
7119     PCCERT_CONTEXT context;
7120     DWORD dwSize;
7121     ALG_ID ai;
7122
7123     /* These crash
7124     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7125     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7126     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7127     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7128      NULL);
7129      */
7130     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7131     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7132      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7133     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7134     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7135      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7136     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7137      &key);
7138     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7139      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7140
7141     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7142     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7143      &key);
7144     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7145
7146     dwSize = sizeof(ai);
7147     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7148     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7149     if(ret)
7150     {
7151       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7152       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7153     }
7154
7155     CryptDestroyKey(key);
7156
7157     /* Repeat with forced algorithm */
7158     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7159      &key);
7160     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7161
7162     dwSize = sizeof(ai);
7163     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7164     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7165     if(ret)
7166     {
7167       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7168       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7169     }
7170
7171     CryptDestroyKey(key);
7172
7173     /* Test importing a public key from a certificate context */
7174     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7175      sizeof(expiredCert));
7176     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7177      GetLastError());
7178     if (context)
7179     {
7180         ok(!strcmp(szOID_RSA_RSA,
7181          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7182          "Expected %s, got %s\n", szOID_RSA_RSA,
7183          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7184         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7185          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7186         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7187         CryptDestroyKey(key);
7188         CertFreeCertificateContext(context);
7189     }
7190 }
7191
7192 static const char cspName[] = "WineCryptTemp";
7193
7194 static void testPortPublicKeyInfo(void)
7195 {
7196     HCRYPTPROV csp;
7197     BOOL ret;
7198     PCERT_PUBLIC_KEY_INFO info = NULL;
7199
7200     /* Just in case a previous run failed, delete this thing */
7201     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7202      CRYPT_DELETEKEYSET);
7203     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7204      CRYPT_NEWKEYSET);
7205
7206     testExportPublicKey(csp, &info);
7207     testImportPublicKey(csp, info);
7208
7209     HeapFree(GetProcessHeap(), 0, info);
7210     CryptReleaseContext(csp, 0);
7211     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7212      CRYPT_DELETEKEYSET);
7213 }
7214
7215 START_TEST(encode)
7216 {
7217     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7218      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7219     HMODULE hCrypt32;
7220     DWORD i;
7221
7222     hCrypt32 = GetModuleHandleA("crypt32.dll");
7223     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7224     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7225     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7226     {
7227         skip("CryptDecodeObjectEx() is not available\n");
7228         return;
7229     }
7230
7231     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7232     {
7233         test_encodeInt(encodings[i]);
7234         test_decodeInt(encodings[i]);
7235         test_encodeEnumerated(encodings[i]);
7236         test_decodeEnumerated(encodings[i]);
7237         test_encodeFiletime(encodings[i]);
7238         test_decodeFiletime(encodings[i]);
7239         test_encodeName(encodings[i]);
7240         test_decodeName(encodings[i]);
7241         test_encodeUnicodeName(encodings[i]);
7242         test_decodeUnicodeName(encodings[i]);
7243         test_encodeNameValue(encodings[i]);
7244         test_decodeNameValue(encodings[i]);
7245         test_encodeUnicodeNameValue(encodings[i]);
7246         test_decodeUnicodeNameValue(encodings[i]);
7247         test_encodeAltName(encodings[i]);
7248         test_decodeAltName(encodings[i]);
7249         test_encodeOctets(encodings[i]);
7250         test_decodeOctets(encodings[i]);
7251         test_encodeBits(encodings[i]);
7252         test_decodeBits(encodings[i]);
7253         test_encodeBasicConstraints(encodings[i]);
7254         test_decodeBasicConstraints(encodings[i]);
7255         test_encodeRsaPublicKey(encodings[i]);
7256         test_decodeRsaPublicKey(encodings[i]);
7257         test_encodeSequenceOfAny(encodings[i]);
7258         test_decodeSequenceOfAny(encodings[i]);
7259         test_encodeExtensions(encodings[i]);
7260         test_decodeExtensions(encodings[i]);
7261         test_encodePublicKeyInfo(encodings[i]);
7262         test_decodePublicKeyInfo(encodings[i]);
7263         test_encodeCertToBeSigned(encodings[i]);
7264         test_decodeCertToBeSigned(encodings[i]);
7265         test_encodeCert(encodings[i]);
7266         test_decodeCert(encodings[i]);
7267         test_encodeCRLDistPoints(encodings[i]);
7268         test_decodeCRLDistPoints(encodings[i]);
7269         test_encodeCRLIssuingDistPoint(encodings[i]);
7270         test_decodeCRLIssuingDistPoint(encodings[i]);
7271         test_encodeCRLToBeSigned(encodings[i]);
7272         test_decodeCRLToBeSigned(encodings[i]);
7273         test_encodeEnhancedKeyUsage(encodings[i]);
7274         test_decodeEnhancedKeyUsage(encodings[i]);
7275         test_encodeAuthorityKeyId(encodings[i]);
7276         test_decodeAuthorityKeyId(encodings[i]);
7277         test_encodeAuthorityKeyId2(encodings[i]);
7278         test_decodeAuthorityKeyId2(encodings[i]);
7279         test_encodeAuthorityInfoAccess(encodings[i]);
7280         test_decodeAuthorityInfoAccess(encodings[i]);
7281         test_encodeCTL(encodings[i]);
7282         test_decodeCTL(encodings[i]);
7283         test_encodePKCSContentInfo(encodings[i]);
7284         test_decodePKCSContentInfo(encodings[i]);
7285         test_encodePKCSAttribute(encodings[i]);
7286         test_decodePKCSAttribute(encodings[i]);
7287         test_encodePKCSAttributes(encodings[i]);
7288         test_decodePKCSAttributes(encodings[i]);
7289         test_encodePKCSSMimeCapabilities(encodings[i]);
7290         test_decodePKCSSMimeCapabilities(encodings[i]);
7291         test_encodePKCSSignerInfo(encodings[i]);
7292         test_decodePKCSSignerInfo(encodings[i]);
7293         test_encodeCMSSignerInfo(encodings[i]);
7294         test_decodeCMSSignerInfo(encodings[i]);
7295         test_encodeNameConstraints(encodings[i]);
7296         test_decodeNameConstraints(encodings[i]);
7297     }
7298     testPortPublicKeyInfo();
7299 }