winmm: Fix a failing mixer test on 98 and ME.
[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) || broken(ret),
473          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
474 }
475
476 static const char *printSystemTime(const SYSTEMTIME *st)
477 {
478     static char buf[25];
479
480     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
481      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
482     return buf;
483 }
484
485 static const char *printFileTime(const FILETIME *ft)
486 {
487     static char buf[25];
488     SYSTEMTIME st;
489
490     FileTimeToSystemTime(ft, &st);
491     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
492      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
493     return buf;
494 }
495
496 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
497 {
498     SYSTEMTIME st;
499
500     FileTimeToSystemTime(got, &st);
501     ok(expected->wYear == st.wYear &&
502      expected->wMonth == st.wMonth &&
503      expected->wDay == st.wDay &&
504      expected->wHour == st.wHour &&
505      expected->wMinute == st.wMinute &&
506      expected->wSecond == st.wSecond &&
507      abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
508      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
509      printSystemTime(expected), printFileTime(got));
510 }
511
512 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
513  const struct encodedFiletime *time)
514 {
515     FILETIME ft = { 0 };
516     DWORD size = sizeof(ft);
517     BOOL ret;
518
519     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
520      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
521     /* years other than 1950-2050 are not allowed for encodings other than
522      * X509_CHOICE_OF_TIME.
523      */
524     if (structType == X509_CHOICE_OF_TIME ||
525      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
526     {
527         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
528          GetLastError());
529         if (ret)
530             compareTime(&time->sysTime, &ft);
531     }
532     else
533         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
534          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
535          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
536          GetLastError());
537 }
538
539 static const BYTE bin20[] = {
540     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
541 static const BYTE bin21[] = {
542     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
543 static const BYTE bin22[] = {
544     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
545
546 static const struct encodedFiletime times[] = {
547  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
548  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
549  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
550 };
551
552 static void test_encodeFiletime(DWORD dwEncoding)
553 {
554     DWORD i;
555
556     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
557     {
558         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
559         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
560         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
561     }
562 }
563
564 static const BYTE bin23[] = {
565     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
566 static const BYTE bin24[] = {
567     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
568 static const BYTE bin25[] = {
569     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
570 static const BYTE bin26[] = {
571     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
572 static const BYTE bin27[] = {
573     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
574 static const BYTE bin28[] = {
575     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
576 static const BYTE bin29[] = {
577     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
578 static const BYTE bin30[] = {
579     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
580 static const BYTE bin31[] = {
581     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
582 static const BYTE bin32[] = {
583     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
584 static const BYTE bin33[] = {
585     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
586 static const BYTE bin34[] = {
587     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
588 static const BYTE bin35[] = {
589     0x17,0x08, '4','5','0','6','0','6','1','6'};
590 static const BYTE bin36[] = {
591     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
592 static const BYTE bin37[] = {
593     0x18,0x04, '2','1','4','5'};
594 static const BYTE bin38[] = {
595     0x18,0x08, '2','1','4','5','0','6','0','6'};
596
597 static void test_decodeFiletime(DWORD dwEncoding)
598 {
599     static const struct encodedFiletime otherTimes[] = {
600      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
601      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
602      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
603      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
604      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
605      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
606      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
607      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
608      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
609      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
610      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
611      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
612     };
613     /* An oddball case that succeeds in Windows, but doesn't seem correct
614      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
615      */
616     static const unsigned char *bogusTimes[] = {
617      /* oddly, this succeeds on Windows, with year 2765
618      "\x18" "\x0f" "21r50606161000Z",
619       */
620      bin35,
621      bin36,
622      bin37,
623      bin38,
624     };
625     DWORD i, size;
626     FILETIME ft1 = { 0 }, ft2 = { 0 };
627     BOOL ret;
628
629     /* Check bogus length with non-NULL buffer */
630     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
631     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
632     size = 1;
633     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
634      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
635     ok(!ret && GetLastError() == ERROR_MORE_DATA,
636      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
637     /* Normal tests */
638     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
639     {
640         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
641         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
642         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
643     }
644     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
645     {
646         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
647         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
648         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
649     }
650     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
651     {
652         size = sizeof(ft1);
653         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
654          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
655         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
656          GetLastError() == OSS_DATA_ERROR /* Win9x */),
657          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
658          GetLastError());
659     }
660 }
661
662 static const char commonName[] = "Juan Lang";
663 static const char surName[] = "Lang";
664
665 static const BYTE emptySequence[] = { 0x30, 0 };
666 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
667 static const BYTE twoRDNs[] = {
668     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
669     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
670     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
671 static const BYTE encodedTwoRDNs[] = {
672 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
673 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
674 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
675 0x6e,0x67,0x00,
676 };
677
678 static const BYTE us[] = { 0x55, 0x53 };
679 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
680  0x74, 0x61 };
681 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
682  0x6f, 0x6c, 0x69, 0x73 };
683 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
684  0x76, 0x65, 0x72, 0x73 };
685 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
686  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
687 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
688  0x73, 0x74 };
689 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
690  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
691
692 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
693 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
694
695 static CHAR oid_us[]            = "2.5.4.6",
696             oid_minnesota[]     = "2.5.4.8",
697             oid_minneapolis[]   = "2.5.4.7",
698             oid_codeweavers[]   = "2.5.4.10",
699             oid_wine[]          = "2.5.4.11",
700             oid_localhostAttr[] = "2.5.4.3",
701             oid_aric[]          = "1.2.840.113549.1.9.1";
702 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
703                                     { RDNA(minnesota) },
704                                     { RDNA(minneapolis) },
705                                     { RDNA(codeweavers) },
706                                     { RDNA(wine) },
707                                     { RDNA(localhostAttr) },
708                                     { RDNIA5(aric) } };
709 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
710                                            { RDNA(localhostAttr) },
711                                            { RDNA(minnesota) },
712                                            { RDNA(minneapolis) },
713                                            { RDNA(codeweavers) },
714                                            { RDNA(wine) },
715                                            { RDNIA5(aric) } };
716
717 #undef RDNIA5
718 #undef RDNA
719
720 static const BYTE encodedRDNAttrs[] = {
721 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
722 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
723 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
724 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
725 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
726 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
727 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
728 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
729 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
730 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
731 };
732
733 static void test_encodeName(DWORD dwEncoding)
734 {
735     CERT_RDN_ATTR attrs[2];
736     CERT_RDN rdn;
737     CERT_NAME_INFO info;
738     static CHAR oid_common_name[] = szOID_COMMON_NAME,
739                 oid_sur_name[]    = szOID_SUR_NAME;
740     BYTE *buf = NULL;
741     DWORD size = 0;
742     BOOL ret;
743
744     if (0)
745     {
746         /* Test with NULL pvStructInfo (crashes on win9x) */
747         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
748          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
749         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
750          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
751     }
752     /* Test with empty CERT_NAME_INFO */
753     info.cRDN = 0;
754     info.rgRDN = NULL;
755     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
756      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
757     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
758     if (buf)
759     {
760         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
761          "Got unexpected encoding for empty name\n");
762         LocalFree(buf);
763     }
764     if (0)
765     {
766         /* Test with bogus CERT_RDN (crashes on win9x) */
767         info.cRDN = 1;
768         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
769          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
770         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
771          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
772     }
773     /* Test with empty CERT_RDN */
774     rdn.cRDNAttr = 0;
775     rdn.rgRDNAttr = NULL;
776     info.cRDN = 1;
777     info.rgRDN = &rdn;
778     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
780     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
781     if (buf)
782     {
783         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
784          "Got unexpected encoding for empty RDN array\n");
785         LocalFree(buf);
786     }
787     if (0)
788     {
789         /* Test with bogus attr array (crashes on win9x) */
790         rdn.cRDNAttr = 1;
791         rdn.rgRDNAttr = NULL;
792         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
793          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
794         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
795          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
796     }
797     /* oddly, a bogus OID is accepted by Windows XP; not testing.
798     attrs[0].pszObjId = "bogus";
799     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
800     attrs[0].Value.cbData = sizeof(commonName);
801     attrs[0].Value.pbData = (BYTE *)commonName;
802     rdn.cRDNAttr = 1;
803     rdn.rgRDNAttr = attrs;
804     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
805      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
806     ok(!ret, "Expected failure, got success\n");
807      */
808     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
809      * the encoded attributes to be swapped.
810      */
811     attrs[0].pszObjId = oid_common_name;
812     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
813     attrs[0].Value.cbData = sizeof(commonName);
814     attrs[0].Value.pbData = (BYTE *)commonName;
815     attrs[1].pszObjId = oid_sur_name;
816     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
817     attrs[1].Value.cbData = sizeof(surName);
818     attrs[1].Value.pbData = (BYTE *)surName;
819     rdn.cRDNAttr = 2;
820     rdn.rgRDNAttr = attrs;
821     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
822      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
823     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
824     if (buf)
825     {
826         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
827          "Got unexpected encoding for two RDN array\n");
828         LocalFree(buf);
829     }
830     /* A name can be "encoded" with previously encoded RDN attrs. */
831     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
832     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
833     attrs[0].Value.cbData = sizeof(twoRDNs);
834     rdn.cRDNAttr = 1;
835     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
836      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
837     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
838     if (buf)
839     {
840         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
841         ok(!memcmp(buf, encodedTwoRDNs, size),
842          "Unexpected value for re-endoded two RDN array\n");
843         LocalFree(buf);
844     }
845     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
846     rdn.cRDNAttr = 1;
847     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
848     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
849      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
850     ok(!ret && GetLastError() == E_INVALIDARG,
851      "Expected E_INVALIDARG, got %08x\n", GetLastError());
852     /* Test a more complex name */
853     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
854     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
855     info.cRDN = 1;
856     info.rgRDN = &rdn;
857     buf = NULL;
858     size = 0;
859     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
860      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
861     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
862     if (ret)
863     {
864         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
865         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
866         LocalFree(buf);
867     }
868 }
869
870 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
871 static WCHAR surNameW[] = { 'L','a','n','g',0 };
872
873 static const BYTE twoRDNsNoNull[] = {
874  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
875  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
876  0x20,0x4c,0x61,0x6e,0x67 };
877 static const BYTE anyType[] = {
878  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
879  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
880  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
881  0x61,0x4c,0x67,0x6e };
882
883 static void test_encodeUnicodeName(DWORD dwEncoding)
884 {
885     CERT_RDN_ATTR attrs[2];
886     CERT_RDN rdn;
887     CERT_NAME_INFO info;
888     static CHAR oid_common_name[] = szOID_COMMON_NAME,
889                 oid_sur_name[]    = szOID_SUR_NAME;
890     BYTE *buf = NULL;
891     DWORD size = 0;
892     BOOL ret;
893
894     if (0)
895     {
896         /* Test with NULL pvStructInfo (crashes on win9x) */
897         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
898          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
899         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
900          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
901     }
902     /* Test with empty CERT_NAME_INFO */
903     info.cRDN = 0;
904     info.rgRDN = NULL;
905     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
906      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
907     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
908     if (buf)
909     {
910         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
911          "Got unexpected encoding for empty name\n");
912         LocalFree(buf);
913     }
914     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
915      * encoding (the NULL).
916      */
917     attrs[0].pszObjId = oid_common_name;
918     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
919     attrs[0].Value.cbData = sizeof(commonNameW);
920     attrs[0].Value.pbData = (BYTE *)commonNameW;
921     rdn.cRDNAttr = 1;
922     rdn.rgRDNAttr = attrs;
923     info.cRDN = 1;
924     info.rgRDN = &rdn;
925     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
926      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
927     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
928      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
929     ok(size == 9, "Unexpected error index %08x\n", size);
930     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
931      * forces the order of the encoded attributes to be swapped.
932      */
933     attrs[0].pszObjId = oid_common_name;
934     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
935     attrs[0].Value.cbData = 0;
936     attrs[0].Value.pbData = (BYTE *)commonNameW;
937     attrs[1].pszObjId = oid_sur_name;
938     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
939     attrs[1].Value.cbData = 0;
940     attrs[1].Value.pbData = (BYTE *)surNameW;
941     rdn.cRDNAttr = 2;
942     rdn.rgRDNAttr = attrs;
943     info.cRDN = 1;
944     info.rgRDN = &rdn;
945     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
946      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
947     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
948     if (buf)
949     {
950         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
951          "Got unexpected encoding for two RDN array\n");
952         LocalFree(buf);
953     }
954     /* A name can be "encoded" with previously encoded RDN attrs. */
955     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
956     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
957     attrs[0].Value.cbData = sizeof(twoRDNs);
958     rdn.cRDNAttr = 1;
959     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
960      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
961     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
962     if (buf)
963     {
964         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
965         ok(!memcmp(buf, encodedTwoRDNs, size),
966          "Unexpected value for re-endoded two RDN array\n");
967         LocalFree(buf);
968     }
969     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
970     rdn.cRDNAttr = 1;
971     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
972     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
973      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
974     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
975     if (buf)
976     {
977         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
978         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
979         LocalFree(buf);
980     }
981 }
982
983 static void compareNameValues(const CERT_NAME_VALUE *expected,
984  const CERT_NAME_VALUE *got)
985 {
986     ok(got->dwValueType == expected->dwValueType,
987      "Expected string type %d, got %d\n", expected->dwValueType,
988      got->dwValueType);
989     ok(got->Value.cbData == expected->Value.cbData,
990      "String type %d: unexpected data size, got %d, expected %d\n",
991      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
992     if (got->Value.cbData && got->Value.pbData)
993         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
994          min(got->Value.cbData, expected->Value.cbData)),
995          "String type %d: unexpected value\n", expected->dwValueType);
996 }
997
998 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
999  const CERT_RDN_ATTR *got)
1000 {
1001     if (expected->pszObjId && strlen(expected->pszObjId))
1002     {
1003         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1004          expected->pszObjId);
1005         if (got->pszObjId)
1006         {
1007             ok(!strcmp(got->pszObjId, expected->pszObjId),
1008              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1009              expected->pszObjId);
1010         }
1011     }
1012     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1013      (const CERT_NAME_VALUE *)&got->dwValueType);
1014 }
1015
1016 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1017 {
1018     ok(got->cRDNAttr == expected->cRDNAttr,
1019      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1020     if (got->cRDNAttr)
1021     {
1022         DWORD i;
1023
1024         for (i = 0; i < got->cRDNAttr; i++)
1025             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1026     }
1027 }
1028
1029 static void compareNames(const CERT_NAME_INFO *expected,
1030  const CERT_NAME_INFO *got)
1031 {
1032     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1033      expected->cRDN, got->cRDN);
1034     if (got->cRDN)
1035     {
1036         DWORD i;
1037
1038         for (i = 0; i < got->cRDN; i++)
1039             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1040     }
1041 }
1042
1043 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1044 static const BYTE twoRDNsExtraBytes[] = {
1045     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1046     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1047     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1048
1049 static void test_decodeName(DWORD dwEncoding)
1050 {
1051     BYTE *buf = NULL;
1052     DWORD bufSize = 0;
1053     BOOL ret;
1054     CERT_RDN rdn;
1055     CERT_NAME_INFO info = { 1, &rdn };
1056
1057     /* test empty name */
1058     bufSize = 0;
1059     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1060      emptySequence[1] + 2,
1061      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1062      (BYTE *)&buf, &bufSize);
1063     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1064     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1065      * decoder works the same way, so only test the count.
1066      */
1067     if (buf)
1068     {
1069         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1070         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1071          "Expected 0 RDNs in empty info, got %d\n",
1072          ((CERT_NAME_INFO *)buf)->cRDN);
1073         LocalFree(buf);
1074     }
1075     /* test empty name with indefinite-length encoding */
1076     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1077      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1078      (BYTE *)&buf, &bufSize);
1079     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1080     if (ret)
1081     {
1082         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1083         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1084          "Expected 0 RDNs in empty info, got %d\n",
1085          ((CERT_NAME_INFO *)buf)->cRDN);
1086         LocalFree(buf);
1087     }
1088     /* test empty RDN */
1089     bufSize = 0;
1090     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1091      emptyRDNs[1] + 2,
1092      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1093      (BYTE *)&buf, &bufSize);
1094     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1095     if (buf)
1096     {
1097         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1098
1099         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1100          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1101          "Got unexpected value for empty RDN\n");
1102         LocalFree(buf);
1103     }
1104     /* test two RDN attrs */
1105     bufSize = 0;
1106     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1107      twoRDNs[1] + 2,
1108      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1109      (BYTE *)&buf, &bufSize);
1110     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1111     if (buf)
1112     {
1113         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1114                     oid_common_name[] = szOID_COMMON_NAME;
1115
1116         CERT_RDN_ATTR attrs[] = {
1117          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1118           (BYTE *)surName } },
1119          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1120           (BYTE *)commonName } },
1121         };
1122
1123         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1124         rdn.rgRDNAttr = attrs;
1125         compareNames(&info, (CERT_NAME_INFO *)buf);
1126         LocalFree(buf);
1127     }
1128     /* test that two RDN attrs with extra bytes succeeds */
1129     bufSize = 0;
1130     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1131      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1132     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1133     /* And, a slightly more complicated name */
1134     buf = NULL;
1135     bufSize = 0;
1136     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1137      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1138     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1139     if (ret)
1140     {
1141         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1142         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1143         compareNames(&info, (CERT_NAME_INFO *)buf);
1144         LocalFree(buf);
1145     }
1146 }
1147
1148 static void test_decodeUnicodeName(DWORD dwEncoding)
1149 {
1150     BYTE *buf = NULL;
1151     DWORD bufSize = 0;
1152     BOOL ret;
1153     CERT_RDN rdn;
1154     CERT_NAME_INFO info = { 1, &rdn };
1155
1156     /* test empty name */
1157     bufSize = 0;
1158     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1159      emptySequence[1] + 2,
1160      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1161      (BYTE *)&buf, &bufSize);
1162     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1163     if (buf)
1164     {
1165         ok(bufSize == sizeof(CERT_NAME_INFO),
1166          "Got wrong bufSize %d\n", bufSize);
1167         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1168          "Expected 0 RDNs in empty info, got %d\n",
1169          ((CERT_NAME_INFO *)buf)->cRDN);
1170         LocalFree(buf);
1171     }
1172     /* test empty RDN */
1173     bufSize = 0;
1174     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1175      emptyRDNs[1] + 2,
1176      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1177      (BYTE *)&buf, &bufSize);
1178     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1179     if (buf)
1180     {
1181         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1182
1183         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1184          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1185          "Got unexpected value for empty RDN\n");
1186         LocalFree(buf);
1187     }
1188     /* test two RDN attrs */
1189     bufSize = 0;
1190     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1191      sizeof(twoRDNsNoNull),
1192      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1193      (BYTE *)&buf, &bufSize);
1194     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1195     if (buf)
1196     {
1197         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1198                     oid_common_name[] = szOID_COMMON_NAME;
1199
1200         CERT_RDN_ATTR attrs[] = {
1201          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1202          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1203          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1204          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1205         };
1206
1207         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1208         rdn.rgRDNAttr = attrs;
1209         compareNames(&info, (CERT_NAME_INFO *)buf);
1210         LocalFree(buf);
1211     }
1212 }
1213
1214 struct EncodedNameValue
1215 {
1216     CERT_NAME_VALUE value;
1217     const BYTE *encoded;
1218     DWORD encodedSize;
1219 };
1220
1221 static const char bogusIA5[] = "\x80";
1222 static const char bogusPrintable[] = "~";
1223 static const char bogusNumeric[] = "A";
1224 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1225 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1226 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1227 static BYTE octetCommonNameValue[] = {
1228  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1229 static BYTE numericCommonNameValue[] = {
1230  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1231 static BYTE printableCommonNameValue[] = {
1232  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1233 static BYTE t61CommonNameValue[] = {
1234  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1235 static BYTE videotexCommonNameValue[] = {
1236  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1237 static BYTE ia5CommonNameValue[] = {
1238  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1239 static BYTE graphicCommonNameValue[] = {
1240  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1241 static BYTE visibleCommonNameValue[] = {
1242  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1243 static BYTE generalCommonNameValue[] = {
1244  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1245 static BYTE bmpCommonNameValue[] = {
1246  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1247  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1248 static BYTE utf8CommonNameValue[] = {
1249  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250
1251 static struct EncodedNameValue nameValues[] = {
1252  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1253      octetCommonNameValue, sizeof(octetCommonNameValue) },
1254  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1255      numericCommonNameValue, sizeof(numericCommonNameValue) },
1256  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1257      printableCommonNameValue, sizeof(printableCommonNameValue) },
1258  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1259      t61CommonNameValue, sizeof(t61CommonNameValue) },
1260  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1261      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1262  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1263      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1264  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1265      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1266  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1267      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1268  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1269      generalCommonNameValue, sizeof(generalCommonNameValue) },
1270  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1271      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1272  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1273      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1274  /* The following tests succeed under Windows, but really should fail,
1275   * they contain characters that are illegal for the encoding.  I'm
1276   * including them to justify my lazy encoding.
1277   */
1278  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1279      sizeof(bin42) },
1280  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1281      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1282  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1283      bin44, sizeof(bin44) },
1284 };
1285
1286 static void test_encodeNameValue(DWORD dwEncoding)
1287 {
1288     BYTE *buf = NULL;
1289     DWORD size = 0, i;
1290     BOOL ret;
1291     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1292
1293     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1294     value.Value.pbData = printableCommonNameValue;
1295     value.Value.cbData = sizeof(printableCommonNameValue);
1296     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1297      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1298     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1299     if (buf)
1300     {
1301         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1302          size);
1303         ok(!memcmp(buf, printableCommonNameValue, size),
1304          "Unexpected encoding\n");
1305         LocalFree(buf);
1306     }
1307     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1308     {
1309         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1310          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1311          &size);
1312         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1313          nameValues[i].value.dwValueType, GetLastError());
1314         if (buf)
1315         {
1316             ok(size == nameValues[i].encodedSize,
1317              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1318             ok(!memcmp(buf, nameValues[i].encoded, size),
1319              "Got unexpected encoding\n");
1320             LocalFree(buf);
1321         }
1322     }
1323 }
1324
1325 static void test_decodeNameValue(DWORD dwEncoding)
1326 {
1327     int i;
1328     BYTE *buf = NULL;
1329     DWORD bufSize = 0;
1330     BOOL ret;
1331
1332     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1333     {
1334         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1335          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1336          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1337          (BYTE *)&buf, &bufSize);
1338         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1339          nameValues[i].value.dwValueType, GetLastError());
1340         if (buf)
1341         {
1342             compareNameValues(&nameValues[i].value,
1343              (const CERT_NAME_VALUE *)buf);
1344             LocalFree(buf);
1345         }
1346     }
1347 }
1348
1349 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1350 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1351 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1352  'h','q','.','o','r','g',0 };
1353 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1354  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1355  0x6f, 0x72, 0x67 };
1356 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1357  0x575b, 0 };
1358 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1359 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1360  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1361 static const BYTE localhost[] = { 127, 0, 0, 1 };
1362 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1363  0x01 };
1364 static const unsigned char encodedCommonName[] = {
1365     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1366 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1367 static const BYTE encodedDirectoryName[] = {
1368 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1369 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1370
1371 static void test_encodeAltName(DWORD dwEncoding)
1372 {
1373     CERT_ALT_NAME_INFO info = { 0 };
1374     CERT_ALT_NAME_ENTRY entry = { 0 };
1375     BYTE *buf = NULL;
1376     DWORD size = 0;
1377     BOOL ret;
1378     char oid[] = "1.2.3";
1379
1380     /* Test with empty info */
1381     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1382      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1383     if (buf)
1384     {
1385         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1386         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1387         LocalFree(buf);
1388     }
1389     /* Test with an empty entry */
1390     info.cAltEntry = 1;
1391     info.rgAltEntry = &entry;
1392     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1393      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1394     ok(!ret && GetLastError() == E_INVALIDARG,
1395      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1396     /* Test with an empty pointer */
1397     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1398     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1399      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1400     if (buf)
1401     {
1402         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1403         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1404         LocalFree(buf);
1405     }
1406     /* Test with a real URL */
1407     U(entry).pwszURL = (LPWSTR)url;
1408     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1409      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1410     if (buf)
1411     {
1412         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1413         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1414         LocalFree(buf);
1415     }
1416     /* Now with the URL containing an invalid IA5 char */
1417     U(entry).pwszURL = (LPWSTR)nihongoURL;
1418     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1419      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1420     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1421      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1422     /* The first invalid character is at index 7 */
1423     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1424      "Expected invalid char at index 7, got %d\n",
1425      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1426     /* Now with the URL missing a scheme */
1427     U(entry).pwszURL = (LPWSTR)dnsName;
1428     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1429      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1430     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1431     if (buf)
1432     {
1433         /* This succeeds, but it shouldn't, so don't worry about conforming */
1434         LocalFree(buf);
1435     }
1436     /* Now with a DNS name */
1437     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1438     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1439      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1440     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1441     if (buf)
1442     {
1443         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1444         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1445         LocalFree(buf);
1446     }
1447     /* Test with an IP address */
1448     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1449     U(entry).IPAddress.cbData = sizeof(localhost);
1450     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1451     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1452      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1453     if (buf)
1454     {
1455         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1456         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1457         LocalFree(buf);
1458     }
1459     /* Test with OID */
1460     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1461     U(entry).pszRegisteredID = oid;
1462     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1463      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1464     if (buf)
1465     {
1466         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1467         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1468         LocalFree(buf);
1469     }
1470     /* Test with directory name */
1471     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1472     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1473     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1474     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1475      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1476     if (buf)
1477     {
1478         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1479         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1480         LocalFree(buf);
1481     }
1482 }
1483
1484 static void test_decodeAltName(DWORD dwEncoding)
1485 {
1486     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1487      0x00, 0x00, 0x01 };
1488     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1489      0x01 };
1490     BOOL ret;
1491     BYTE *buf = NULL;
1492     DWORD bufSize = 0;
1493     CERT_ALT_NAME_INFO *info;
1494
1495     /* Test some bogus ones first */
1496     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1497      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1498      NULL, (BYTE *)&buf, &bufSize);
1499     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1500      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1501      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1502      GetLastError());
1503     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1504      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1505      &bufSize);
1506     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1507      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1508      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1509      GetLastError());
1510     /* Now expected cases */
1511     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1512      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1513      &bufSize);
1514     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1515     if (buf)
1516     {
1517         info = (CERT_ALT_NAME_INFO *)buf;
1518
1519         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1520          info->cAltEntry);
1521         LocalFree(buf);
1522     }
1523     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1524      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1525      &bufSize);
1526     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1527     if (buf)
1528     {
1529         info = (CERT_ALT_NAME_INFO *)buf;
1530
1531         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1532          info->cAltEntry);
1533         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1534          "Expected CERT_ALT_NAME_URL, got %d\n",
1535          info->rgAltEntry[0].dwAltNameChoice);
1536         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1537          "Expected empty URL\n");
1538         LocalFree(buf);
1539     }
1540     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1541      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1542     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1543     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1544      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1545      &bufSize);
1546     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1547     if (buf)
1548     {
1549         info = (CERT_ALT_NAME_INFO *)buf;
1550
1551         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1552          info->cAltEntry);
1553         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1554          "Expected CERT_ALT_NAME_URL, got %d\n",
1555          info->rgAltEntry[0].dwAltNameChoice);
1556         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1557         LocalFree(buf);
1558     }
1559     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1560      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1561      &bufSize);
1562     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1563     if (buf)
1564     {
1565         info = (CERT_ALT_NAME_INFO *)buf;
1566
1567         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1568          info->cAltEntry);
1569         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1570          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1571          info->rgAltEntry[0].dwAltNameChoice);
1572         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1573          "Unexpected DNS name\n");
1574         LocalFree(buf);
1575     }
1576     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1577      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1578      &bufSize);
1579     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1580     if (buf)
1581     {
1582         info = (CERT_ALT_NAME_INFO *)buf;
1583
1584         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1585          info->cAltEntry);
1586         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1587          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1588          info->rgAltEntry[0].dwAltNameChoice);
1589         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1590          "Unexpected IP address length %d\n",
1591           U(info->rgAltEntry[0]).IPAddress.cbData);
1592         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1593          sizeof(localhost)), "Unexpected IP address value\n");
1594         LocalFree(buf);
1595     }
1596     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1597      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1598      &bufSize);
1599     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1600     if (buf)
1601     {
1602         info = (CERT_ALT_NAME_INFO *)buf;
1603
1604         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1605          info->cAltEntry);
1606         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1607          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1608          info->rgAltEntry[0].dwAltNameChoice);
1609         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1610            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1611         LocalFree(buf);
1612     }
1613     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1614      encodedDirectoryName, sizeof(encodedDirectoryName),
1615      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1616     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1617     if (buf)
1618     {
1619         info = (CERT_ALT_NAME_INFO *)buf;
1620
1621         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1622          info->cAltEntry);
1623         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1624          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1625          info->rgAltEntry[0].dwAltNameChoice);
1626         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1627          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1628           U(info->rgAltEntry[0]).DirectoryName.cbData);
1629         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1630          encodedCommonName, sizeof(encodedCommonName)),
1631          "Unexpected directory name value\n");
1632         LocalFree(buf);
1633     }
1634 }
1635
1636 struct UnicodeExpectedError
1637 {
1638     DWORD   valueType;
1639     LPCWSTR str;
1640     DWORD   errorIndex;
1641     DWORD   error;
1642 };
1643
1644 static const WCHAR oneW[] = { '1',0 };
1645 static const WCHAR aW[] = { 'a',0 };
1646 static const WCHAR quoteW[] = { '"', 0 };
1647
1648 static struct UnicodeExpectedError unicodeErrors[] = {
1649  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1650  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1651  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1652  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1653  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1654  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1655 };
1656
1657 struct UnicodeExpectedResult
1658 {
1659     DWORD           valueType;
1660     LPCWSTR         str;
1661     CRYPT_DATA_BLOB encoded;
1662 };
1663
1664 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1665 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1666 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1667 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1668 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1669 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1670 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1671 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1672 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1673 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1674 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1675 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1676  0x5b };
1677 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1678  0x6f,0x5b };
1679 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1680  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1681 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1682  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1683
1684 static struct UnicodeExpectedResult unicodeResults[] = {
1685  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1686  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1687  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1688  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1689  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1690  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1691  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1692  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1693  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1694  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1695  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1696  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1697  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1698 };
1699
1700 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1701  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1702  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1703 };
1704
1705 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1706 {
1707     BYTE *buf = NULL;
1708     DWORD size = 0, i;
1709     BOOL ret;
1710     CERT_NAME_VALUE value;
1711
1712     if (0)
1713     {
1714         /* Crashes on win9x */
1715         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1716          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1717         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1718          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1719     }
1720     /* Have to have a string of some sort */
1721     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1722     value.Value.pbData = NULL;
1723     value.Value.cbData = 0;
1724     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1725      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1726     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1727      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1728     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1729     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1730      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1731     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1732      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1733     value.dwValueType = CERT_RDN_ANY_TYPE;
1734     value.Value.pbData = (LPBYTE)oneW;
1735     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1737     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739     value.Value.cbData = sizeof(oneW);
1740     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1742     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744     /* An encoded string with specified length isn't good enough either */
1745     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1746     value.Value.pbData = oneUniversal;
1747     value.Value.cbData = sizeof(oneUniversal);
1748     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1749      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1750     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1751      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1752     /* More failure checking */
1753     value.Value.cbData = 0;
1754     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1755     {
1756         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1757         value.dwValueType = unicodeErrors[i].valueType;
1758         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1759          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1760         ok(!ret && GetLastError() == unicodeErrors[i].error,
1761          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1762          unicodeErrors[i].error, GetLastError());
1763         ok(size == unicodeErrors[i].errorIndex,
1764          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1765          size);
1766     }
1767     /* cbData can be zero if the string is NULL-terminated */
1768     value.Value.cbData = 0;
1769     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1770     {
1771         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1772         value.dwValueType = unicodeResults[i].valueType;
1773         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1774          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1775         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1776          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1777         if (buf)
1778         {
1779             ok(size == unicodeResults[i].encoded.cbData,
1780              "Value type %d: expected size %d, got %d\n",
1781              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1782             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1783              "Value type %d: unexpected value\n", value.dwValueType);
1784             LocalFree(buf);
1785         }
1786     }
1787     /* These "encode," but they do so by truncating each unicode character
1788      * rather than properly encoding it.  Kept separate from the proper results,
1789      * because the encoded forms won't decode to their original strings.
1790      */
1791     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1792     {
1793         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1794         value.dwValueType = unicodeWeirdness[i].valueType;
1795         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1796          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1797         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1798         if (buf)
1799         {
1800             ok(size == unicodeWeirdness[i].encoded.cbData,
1801              "Value type %d: expected size %d, got %d\n",
1802              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1803             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1804              "Value type %d: unexpected value\n", value.dwValueType);
1805             LocalFree(buf);
1806         }
1807     }
1808 }
1809
1810 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1811 {
1812     if (n <= 0) return 0;
1813     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1814     return *str1 - *str2;
1815 }
1816
1817 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1818 {
1819     DWORD i;
1820
1821     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1822     {
1823         BYTE *buf = NULL;
1824         BOOL ret;
1825         DWORD size = 0;
1826
1827         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1828          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1829          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1830         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1831          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1832         if (ret && buf)
1833         {
1834             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1835
1836             ok(value->dwValueType == unicodeResults[i].valueType,
1837              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1838              value->dwValueType);
1839             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1840              value->Value.cbData / sizeof(WCHAR)),
1841              "Unexpected decoded value for index %d (value type %d)\n", i,
1842              unicodeResults[i].valueType);
1843             LocalFree(buf);
1844         }
1845     }
1846 }
1847
1848 struct encodedOctets
1849 {
1850     const BYTE *val;
1851     const BYTE *encoded;
1852 };
1853
1854 static const unsigned char bin46[] = { 'h','i',0 };
1855 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1856 static const unsigned char bin48[] = {
1857      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1858 static const unsigned char bin49[] = {
1859      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1860 static const unsigned char bin50[] = { 0 };
1861 static const unsigned char bin51[] = { 0x04,0x00,0 };
1862
1863 static const struct encodedOctets octets[] = {
1864     { bin46, bin47 },
1865     { bin48, bin49 },
1866     { bin50, bin51 },
1867 };
1868
1869 static void test_encodeOctets(DWORD dwEncoding)
1870 {
1871     CRYPT_DATA_BLOB blob;
1872     DWORD i;
1873
1874     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1875     {
1876         BYTE *buf = NULL;
1877         BOOL ret;
1878         DWORD bufSize = 0;
1879
1880         blob.cbData = strlen((const char*)octets[i].val);
1881         blob.pbData = (BYTE*)octets[i].val;
1882         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1883          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1884         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1885         if (buf)
1886         {
1887             ok(buf[0] == 4,
1888              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1889             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1890              buf[1], octets[i].encoded[1]);
1891             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1892              octets[i].encoded[1] + 1), "Got unexpected value\n");
1893             LocalFree(buf);
1894         }
1895     }
1896 }
1897
1898 static void test_decodeOctets(DWORD dwEncoding)
1899 {
1900     DWORD i;
1901
1902     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1903     {
1904         BYTE *buf = NULL;
1905         BOOL ret;
1906         DWORD bufSize = 0;
1907
1908         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1909          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1910          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1911         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1912         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1913          "Expected size >= %d, got %d\n",
1914            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1915         ok(buf != NULL, "Expected allocated buffer\n");
1916         if (buf)
1917         {
1918             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1919
1920             if (blob->cbData)
1921                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1922                  "Unexpected value\n");
1923             LocalFree(buf);
1924         }
1925     }
1926 }
1927
1928 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1929
1930 struct encodedBits
1931 {
1932     DWORD cUnusedBits;
1933     const BYTE *encoded;
1934     DWORD cbDecoded;
1935     const BYTE *decoded;
1936 };
1937
1938 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1939 static const unsigned char bin53[] = { 0xff,0xff };
1940 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1941 static const unsigned char bin55[] = { 0xff,0xfe };
1942 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1943 static const unsigned char bin57[] = { 0xfe };
1944 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1945
1946 static const struct encodedBits bits[] = {
1947     /* normal test cases */
1948     { 0, bin52, 2, bin53 },
1949     { 1, bin54, 2, bin55 },
1950     /* strange test case, showing cUnusedBits >= 8 is allowed */
1951     { 9, bin56, 1, bin57 },
1952     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1953     { 17, bin58, 0, NULL },
1954 };
1955
1956 static void test_encodeBits(DWORD dwEncoding)
1957 {
1958     DWORD i;
1959
1960     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1961     {
1962         CRYPT_BIT_BLOB blob;
1963         BOOL ret;
1964         BYTE *buf = NULL;
1965         DWORD bufSize = 0;
1966
1967         blob.cbData = sizeof(bytesToEncode);
1968         blob.pbData = (BYTE *)bytesToEncode;
1969         blob.cUnusedBits = bits[i].cUnusedBits;
1970         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1971          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1972         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1973         if (buf)
1974         {
1975             ok(bufSize == bits[i].encoded[1] + 2,
1976              "Got unexpected size %d, expected %d\n", bufSize,
1977              bits[i].encoded[1] + 2);
1978             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1979              "Unexpected value\n");
1980             LocalFree(buf);
1981         }
1982     }
1983 }
1984
1985 static void test_decodeBits(DWORD dwEncoding)
1986 {
1987     static const BYTE ber[] = "\x03\x02\x01\xff";
1988     static const BYTE berDecoded = 0xfe;
1989     DWORD i;
1990     BOOL ret;
1991     BYTE *buf = NULL;
1992     DWORD bufSize = 0;
1993
1994     /* normal cases */
1995     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1996     {
1997         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1998          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1999          &bufSize);
2000         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2001         if (buf)
2002         {
2003             CRYPT_BIT_BLOB *blob;
2004
2005             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2006                "Got unexpected size %d\n", bufSize);
2007             blob = (CRYPT_BIT_BLOB *)buf;
2008             ok(blob->cbData == bits[i].cbDecoded,
2009              "Got unexpected length %d, expected %d\n", blob->cbData,
2010              bits[i].cbDecoded);
2011             if (blob->cbData && bits[i].cbDecoded)
2012                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2013                  "Unexpected value\n");
2014             LocalFree(buf);
2015         }
2016     }
2017     /* special case: check that something that's valid in BER but not in DER
2018      * decodes successfully
2019      */
2020     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2021      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2022     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2023     if (buf)
2024     {
2025         CRYPT_BIT_BLOB *blob;
2026
2027         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2028            "Got unexpected size %d\n", bufSize);
2029         blob = (CRYPT_BIT_BLOB *)buf;
2030         ok(blob->cbData == sizeof(berDecoded),
2031            "Got unexpected length %d\n", blob->cbData);
2032         if (blob->cbData)
2033             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2034         LocalFree(buf);
2035     }
2036 }
2037
2038 struct Constraints2
2039 {
2040     CERT_BASIC_CONSTRAINTS2_INFO info;
2041     const BYTE *encoded;
2042 };
2043
2044 static const unsigned char bin59[] = { 0x30,0x00 };
2045 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2046 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2047 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2048 static const struct Constraints2 constraints2[] = {
2049  /* empty constraints */
2050  { { FALSE, FALSE, 0}, bin59 },
2051  /* can be a CA */
2052  { { TRUE,  FALSE, 0}, bin60 },
2053  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2054   * but that's not the case
2055   */
2056  { { FALSE, TRUE,  0}, bin61 },
2057  /* can be a CA and has path length constraints set */
2058  { { TRUE,  TRUE,  1}, bin62 },
2059 };
2060
2061 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2062 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2063  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2064  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2065  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2066 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2067  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2068  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2069  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2070  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2071
2072 static void test_encodeBasicConstraints(DWORD dwEncoding)
2073 {
2074     DWORD i, bufSize = 0;
2075     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2076     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2077      (LPBYTE)encodedDomainName };
2078     BOOL ret;
2079     BYTE *buf = NULL;
2080
2081     /* First test with the simpler info2 */
2082     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2083     {
2084         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2085          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2086          &bufSize);
2087         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2088         if (buf)
2089         {
2090             ok(bufSize == constraints2[i].encoded[1] + 2,
2091              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2092              bufSize);
2093             ok(!memcmp(buf, constraints2[i].encoded,
2094              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2095             LocalFree(buf);
2096         }
2097     }
2098     /* Now test with more complex basic constraints */
2099     info.SubjectType.cbData = 0;
2100     info.fPathLenConstraint = FALSE;
2101     info.cSubtreesConstraint = 0;
2102     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2103      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2104     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2105      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2106     if (buf)
2107     {
2108         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2109         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2110          "Unexpected value\n");
2111         LocalFree(buf);
2112     }
2113     /* None of the certs I examined had any subtree constraint, but I test one
2114      * anyway just in case.
2115      */
2116     info.cSubtreesConstraint = 1;
2117     info.rgSubtreesConstraint = &nameBlob;
2118     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2119      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2120     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2121      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2122     if (buf)
2123     {
2124         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2125         ok(!memcmp(buf, constraintWithDomainName,
2126          sizeof(constraintWithDomainName)), "Unexpected value\n");
2127         LocalFree(buf);
2128     }
2129     /* FIXME: test encoding with subject type. */
2130 }
2131
2132 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2133
2134 static void test_decodeBasicConstraints(DWORD dwEncoding)
2135 {
2136     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2137      0xff };
2138     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2139     DWORD i;
2140     BOOL ret;
2141     BYTE *buf = NULL;
2142     DWORD bufSize = 0;
2143
2144     /* First test with simpler info2 */
2145     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2146     {
2147         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2148          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2149          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2150         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2151          GetLastError());
2152         if (buf)
2153         {
2154             CERT_BASIC_CONSTRAINTS2_INFO *info =
2155              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2156
2157             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2158              "Unexpected value for item %d\n", i);
2159             LocalFree(buf);
2160         }
2161     }
2162     /* Check with the order of encoded elements inverted */
2163     buf = (PBYTE)1;
2164     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2165      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2166      &bufSize);
2167     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2168      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2169      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2170      GetLastError());
2171     ok(!buf, "Expected buf to be set to NULL\n");
2172     /* Check with a non-DER bool */
2173     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2174      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2175      (BYTE *)&buf, &bufSize);
2176     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2177     if (buf)
2178     {
2179         CERT_BASIC_CONSTRAINTS2_INFO *info =
2180          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2181
2182         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2183         LocalFree(buf);
2184     }
2185     /* Check with a non-basic constraints value */
2186     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2187      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2188      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2189     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2190      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2191      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2192      GetLastError());
2193     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2194     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2195      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2196      (BYTE *)&buf, &bufSize);
2197     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2198     if (buf)
2199     {
2200         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2201
2202         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2203         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2204         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2205         LocalFree(buf);
2206     }
2207     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2208      constraintWithDomainName, sizeof(constraintWithDomainName),
2209      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2210     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2211     if (buf)
2212     {
2213         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2214
2215         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2216         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2217         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2218         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2219         {
2220             ok(info->rgSubtreesConstraint[0].cbData ==
2221              sizeof(encodedDomainName), "Wrong size %d\n",
2222              info->rgSubtreesConstraint[0].cbData);
2223             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2224              sizeof(encodedDomainName)), "Unexpected value\n");
2225         }
2226         LocalFree(buf);
2227     }
2228 }
2229
2230 /* These are terrible public keys of course, I'm just testing encoding */
2231 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2232 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2233 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2234 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2235 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2236 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2237 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2238 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2239
2240 struct EncodedRSAPubKey
2241 {
2242     const BYTE *modulus;
2243     size_t modulusLen;
2244     const BYTE *encoded;
2245     size_t decodedModulusLen;
2246 };
2247
2248 struct EncodedRSAPubKey rsaPubKeys[] = {
2249     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2250     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2251     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2252     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2253 };
2254
2255 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2256 {
2257     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2258     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2259     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2260     BOOL ret;
2261     BYTE *buf = NULL;
2262     DWORD bufSize = 0, i;
2263
2264     /* Try with a bogus blob type */
2265     hdr->bType = 2;
2266     hdr->bVersion = CUR_BLOB_VERSION;
2267     hdr->reserved = 0;
2268     hdr->aiKeyAlg = CALG_RSA_KEYX;
2269     rsaPubKey->magic = 0x31415352;
2270     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2271     rsaPubKey->pubexp = 65537;
2272     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2273      sizeof(modulus1));
2274
2275     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2276      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2277      &bufSize);
2278     ok(!ret && GetLastError() == E_INVALIDARG,
2279      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2280     /* Now with a bogus reserved field */
2281     hdr->bType = PUBLICKEYBLOB;
2282     hdr->reserved = 1;
2283     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2284      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2285      &bufSize);
2286     if (buf)
2287     {
2288         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2289          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2290         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2291         LocalFree(buf);
2292     }
2293     /* Now with a bogus blob version */
2294     hdr->reserved = 0;
2295     hdr->bVersion = 0;
2296     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2297      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2298      &bufSize);
2299     if (buf)
2300     {
2301         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2302          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2303         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2304         LocalFree(buf);
2305     }
2306     /* And with a bogus alg ID */
2307     hdr->bVersion = CUR_BLOB_VERSION;
2308     hdr->aiKeyAlg = CALG_DES;
2309     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2310      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2311      &bufSize);
2312     if (buf)
2313     {
2314         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2315          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2316         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2317         LocalFree(buf);
2318     }
2319     /* Check a couple of RSA-related OIDs */
2320     hdr->aiKeyAlg = CALG_RSA_KEYX;
2321     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2322      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2323     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2324      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2325     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2326      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2327     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2328      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2329     /* Finally, all valid */
2330     hdr->aiKeyAlg = CALG_RSA_KEYX;
2331     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2332     {
2333         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2334          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2335         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2336          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2337         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2338         if (buf)
2339         {
2340             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2341              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2342              bufSize);
2343             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2344              "Unexpected value\n");
2345             LocalFree(buf);
2346         }
2347     }
2348 }
2349
2350 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2351 {
2352     DWORD i;
2353     LPBYTE buf = NULL;
2354     DWORD bufSize = 0;
2355     BOOL ret;
2356
2357     /* Try with a bad length */
2358     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2359      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2360      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2361     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2362      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2363     /* Try with a couple of RSA-related OIDs */
2364     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2365      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2366      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2367     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2368      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2369     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2370      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2371      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2372     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2373      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2374     /* Now try success cases */
2375     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2376     {
2377         bufSize = 0;
2378         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2379          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2380          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2381         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2382         if (buf)
2383         {
2384             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2385             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2386
2387             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2388              rsaPubKeys[i].decodedModulusLen,
2389              "Wrong size %d\n", bufSize);
2390             ok(hdr->bType == PUBLICKEYBLOB,
2391              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2392              hdr->bType);
2393             ok(hdr->bVersion == CUR_BLOB_VERSION,
2394              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2395              CUR_BLOB_VERSION, hdr->bVersion);
2396             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2397              hdr->reserved);
2398             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2399              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2400             ok(rsaPubKey->magic == 0x31415352,
2401              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2402             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2403              "Wrong bit len %d\n", rsaPubKey->bitlen);
2404             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2405              rsaPubKey->pubexp);
2406             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2407              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2408              "Unexpected modulus\n");
2409             LocalFree(buf);
2410         }
2411     }
2412 }
2413
2414 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2415  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2416  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2417
2418 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2419  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2420  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2421  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2422
2423 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2424 {
2425     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2426     CRYPT_SEQUENCE_OF_ANY seq;
2427     DWORD i;
2428     BOOL ret;
2429     BYTE *buf = NULL;
2430     DWORD bufSize = 0;
2431
2432     /* Encode a homogeneous sequence */
2433     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2434     {
2435         blobs[i].cbData = ints[i].encoded[1] + 2;
2436         blobs[i].pbData = (BYTE *)ints[i].encoded;
2437     }
2438     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2439     seq.rgValue = blobs;
2440
2441     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2442      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2443     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2444     if (buf)
2445     {
2446         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2447         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2448         LocalFree(buf);
2449     }
2450     /* Change the type of the first element in the sequence, and give it
2451      * another go
2452      */
2453     blobs[0].cbData = times[0].encodedTime[1] + 2;
2454     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2455     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2456      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2457     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2458     if (buf)
2459     {
2460         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2461         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2462          "Unexpected value\n");
2463         LocalFree(buf);
2464     }
2465 }
2466
2467 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2468 {
2469     BOOL ret;
2470     BYTE *buf = NULL;
2471     DWORD bufSize = 0;
2472
2473     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2474      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2475     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2476     if (buf)
2477     {
2478         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2479         DWORD i;
2480
2481         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2482          "Wrong elements %d\n", seq->cValue);
2483         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2484         {
2485             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2486              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2487              seq->rgValue[i].cbData);
2488             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2489              ints[i].encoded[1] + 2), "Unexpected value\n");
2490         }
2491         LocalFree(buf);
2492     }
2493     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2494      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2495      &bufSize);
2496     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2497     if (buf)
2498     {
2499         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2500
2501         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2502          "Wrong elements %d\n", seq->cValue);
2503         /* Just check the first element since it's all that changed */
2504         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2505          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2506          seq->rgValue[0].cbData);
2507         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2508          times[0].encodedTime[1] + 2), "Unexpected value\n");
2509         LocalFree(buf);
2510     }
2511 }
2512
2513 struct encodedExtensions
2514 {
2515     CERT_EXTENSIONS exts;
2516     const BYTE *encoded;
2517 };
2518
2519 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2520 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2521 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2522 static CERT_EXTENSION criticalExt =
2523  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2524 static CERT_EXTENSION nonCriticalExt =
2525  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2526
2527 static const BYTE ext0[] = { 0x30,0x00 };
2528 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2529                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2530 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2531                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2532
2533 static const struct encodedExtensions exts[] = {
2534  { { 0, NULL }, ext0 },
2535  { { 1, &criticalExt }, ext1 },
2536  { { 1, &nonCriticalExt }, ext2 },
2537 };
2538
2539 static void test_encodeExtensions(DWORD dwEncoding)
2540 {
2541     DWORD i;
2542
2543     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2544     {
2545         BOOL ret;
2546         BYTE *buf = NULL;
2547         DWORD bufSize = 0;
2548
2549         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2550          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2551         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2552         if (buf)
2553         {
2554             ok(bufSize == exts[i].encoded[1] + 2,
2555              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2556             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2557              "Unexpected value\n");
2558             LocalFree(buf);
2559         }
2560     }
2561 }
2562
2563 static void test_decodeExtensions(DWORD dwEncoding)
2564 {
2565     DWORD i;
2566
2567     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2568     {
2569         BOOL ret;
2570         BYTE *buf = NULL;
2571         DWORD bufSize = 0;
2572
2573         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2574          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2575          NULL, (BYTE *)&buf, &bufSize);
2576         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2577         if (buf)
2578         {
2579             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2580             DWORD j;
2581
2582             ok(ext->cExtension == exts[i].exts.cExtension,
2583              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2584              ext->cExtension);
2585             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2586             {
2587                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2588                  exts[i].exts.rgExtension[j].pszObjId),
2589                  "Expected OID %s, got %s\n",
2590                  exts[i].exts.rgExtension[j].pszObjId,
2591                  ext->rgExtension[j].pszObjId);
2592                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2593                  exts[i].exts.rgExtension[j].Value.pbData,
2594                  exts[i].exts.rgExtension[j].Value.cbData),
2595                  "Unexpected value\n");
2596             }
2597             LocalFree(buf);
2598         }
2599     }
2600 }
2601
2602 /* MS encodes public key info with a NULL if the algorithm identifier's
2603  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2604  * it encodes them by omitting the algorithm parameters.  This latter approach
2605  * seems more correct, so accept either form.
2606  */
2607 struct encodedPublicKey
2608 {
2609     CERT_PUBLIC_KEY_INFO info;
2610     const BYTE *encoded;
2611     const BYTE *encodedNoNull;
2612     CERT_PUBLIC_KEY_INFO decoded;
2613 };
2614
2615 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2616  0xe, 0xf };
2617 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2618
2619 static const unsigned char bin64[] = {
2620     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2621 static const unsigned char bin65[] = {
2622     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2623 static const unsigned char bin66[] = {
2624     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2625 static const unsigned char bin67[] = {
2626     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2627 static const unsigned char bin68[] = {
2628     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2629     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2630 static const unsigned char bin69[] = {
2631     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2632     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2633 static const unsigned char bin70[] = {
2634     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2635     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2636     0x0f};
2637 static const unsigned char bin71[] = {
2638     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2639     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2640     0x0f};
2641 static unsigned char bin72[] = { 0x05,0x00};
2642
2643 static CHAR oid_bogus[] = "1.2.3",
2644             oid_rsa[]   = szOID_RSA;
2645
2646 static const struct encodedPublicKey pubKeys[] = {
2647  /* with a bogus OID */
2648  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2649   bin64, bin65,
2650   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2651  /* some normal keys */
2652  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2653   bin66, bin67,
2654   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2655  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2656   bin68, bin69,
2657   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2658  /* with add'l parameters--note they must be DER-encoded */
2659  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2660   (BYTE *)aKey, 0 } },
2661   bin70, bin71,
2662   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2663   (BYTE *)aKey, 0 } } },
2664 };
2665
2666 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2667 {
2668     DWORD i;
2669
2670     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2671     {
2672         BOOL ret;
2673         BYTE *buf = NULL;
2674         DWORD bufSize = 0;
2675
2676         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2677          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2678          &bufSize);
2679         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2680          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2681         if (buf)
2682         {
2683             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2684              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2685              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2686              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2687             if (bufSize == pubKeys[i].encoded[1] + 2)
2688                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2689                  "Unexpected value\n");
2690             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2691                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2692                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2693             LocalFree(buf);
2694         }
2695     }
2696 }
2697
2698 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2699  const CERT_PUBLIC_KEY_INFO *got)
2700 {
2701     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2702      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2703      got->Algorithm.pszObjId);
2704     ok(expected->Algorithm.Parameters.cbData ==
2705      got->Algorithm.Parameters.cbData,
2706      "Expected parameters of %d bytes, got %d\n",
2707      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2708     if (expected->Algorithm.Parameters.cbData)
2709         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2710          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2711          "Unexpected algorithm parameters\n");
2712     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2713      "Expected public key of %d bytes, got %d\n",
2714      expected->PublicKey.cbData, got->PublicKey.cbData);
2715     if (expected->PublicKey.cbData)
2716         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2717          got->PublicKey.cbData), "Unexpected public key value\n");
2718 }
2719
2720 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2721 {
2722     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2723      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2724      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2725      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2726     DWORD i;
2727     BOOL ret;
2728     BYTE *buf = NULL;
2729     DWORD bufSize = 0;
2730
2731     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2732     {
2733         /* The NULL form decodes to the decoded member */
2734         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2735          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2736          NULL, (BYTE *)&buf, &bufSize);
2737         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2738         if (buf)
2739         {
2740             comparePublicKeyInfo(&pubKeys[i].decoded,
2741              (CERT_PUBLIC_KEY_INFO *)buf);
2742             LocalFree(buf);
2743         }
2744         /* The non-NULL form decodes to the original */
2745         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2746          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2747          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2748         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2749         if (buf)
2750         {
2751             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2752             LocalFree(buf);
2753         }
2754     }
2755     /* Test with bogus (not valid DER) parameters */
2756     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2757      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2758      NULL, (BYTE *)&buf, &bufSize);
2759     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2760      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2761      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2762      GetLastError());
2763 }
2764
2765 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2766  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2767  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2768  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2769  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2770 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2771  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2772  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2773  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2774  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2775 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2776  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2777  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2778  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2779  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2780 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2781  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2782  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2783  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2784  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2785  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2786  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2787 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2788  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2789  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2790  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2791  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2792  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2793  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2794 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2795  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2796  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2797  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2798  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2799  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2800  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2801  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2802  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2803  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2804 static const BYTE v1CertWithPubKey[] = {
2805 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2806 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2807 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2808 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2809 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2810 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2811 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2812 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2813 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2814 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2815 0x01,0x01 };
2816 static const BYTE v1CertWithPubKeyNoNull[] = {
2817 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2818 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2819 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2820 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2821 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2822 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2823 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2824 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2825 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2826 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2827 static const BYTE v1CertWithSubjectKeyId[] = {
2828 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2829 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2830 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2831 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2832 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2833 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2834 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2835 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2836 0x4c,0x61,0x6e,0x67,0x00 };
2837
2838 static const BYTE serialNum[] = { 0x01 };
2839
2840 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2841 {
2842     BOOL ret;
2843     BYTE *buf = NULL;
2844     DWORD size = 0;
2845     CERT_INFO info = { 0 };
2846     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2847     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2848     CERT_EXTENSION ext;
2849
2850     if (0)
2851     {
2852         /* Test with NULL pvStructInfo (crashes on win9x) */
2853         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2854          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2855         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2856          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2857     }
2858     /* Test with a V1 cert */
2859     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2860      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2861     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2862      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2863     if (buf)
2864     {
2865         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2866          v1Cert[1] + 2, size);
2867         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2868         LocalFree(buf);
2869     }
2870     /* Test v2 cert */
2871     info.dwVersion = CERT_V2;
2872     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2873      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2874     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2875      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2876     if (buf)
2877     {
2878         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2879         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2880         LocalFree(buf);
2881     }
2882     /* Test v3 cert */
2883     info.dwVersion = CERT_V3;
2884     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2885      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2886     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2887      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2888     if (buf)
2889     {
2890         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2891         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2892         LocalFree(buf);
2893     }
2894     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2895      * API doesn't prevent it)
2896      */
2897     info.dwVersion = CERT_V1;
2898     info.cExtension = 1;
2899     info.rgExtension = &criticalExt;
2900     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2901      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2902     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2903      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2904     if (buf)
2905     {
2906         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2907         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2908         LocalFree(buf);
2909     }
2910     /* test v1 cert with a serial number */
2911     info.SerialNumber.cbData = sizeof(serialNum);
2912     info.SerialNumber.pbData = (BYTE *)serialNum;
2913     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2914      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2915     if (buf)
2916     {
2917         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2918         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2919         LocalFree(buf);
2920     }
2921     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2922     info.Issuer.cbData = sizeof(encodedCommonName);
2923     info.Issuer.pbData = (BYTE *)encodedCommonName;
2924     info.Subject.cbData = sizeof(encodedCommonName);
2925     info.Subject.pbData = (BYTE *)encodedCommonName;
2926     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2927      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2928     if (buf)
2929     {
2930         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2931         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2932         LocalFree(buf);
2933     }
2934     /* Add a public key */
2935     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2936     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2937     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2938     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2939      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2940     if (buf)
2941     {
2942         ok(size == sizeof(v1CertWithPubKey) ||
2943          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2944         if (size == sizeof(v1CertWithPubKey))
2945             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2946         else if (size == sizeof(v1CertWithPubKeyNoNull))
2947             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2948              "Got unexpected value\n");
2949         LocalFree(buf);
2950     }
2951     /* Remove the public key, and add a subject key identifier extension */
2952     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2953     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2954     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2955     ext.pszObjId = oid_subject_key_identifier;
2956     ext.fCritical = FALSE;
2957     ext.Value.cbData = sizeof(octetCommonNameValue);
2958     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2959     info.cExtension = 1;
2960     info.rgExtension = &ext;
2961     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2962      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2963     if (buf)
2964     {
2965         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2966         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2967         LocalFree(buf);
2968     }
2969 }
2970
2971 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2972 {
2973     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2974      v1CertWithConstraints, v1CertWithSerial };
2975     BOOL ret;
2976     BYTE *buf = NULL;
2977     DWORD size = 0, i;
2978
2979     /* Test with NULL pbEncoded */
2980     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2981      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2982     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2983      GetLastError() == OSS_BAD_ARG /* Win9x */),
2984      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2985     if (0)
2986     {
2987         /* Crashes on win9x */
2988         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2989          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2990         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2991          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2992     }
2993     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2994      * minimum a cert must have a non-zero serial number, an issuer, and a
2995      * subject.
2996      */
2997     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2998     {
2999         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3000          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3001          (BYTE *)&buf, &size);
3002         ok(!ret, "Expected failure\n");
3003     }
3004     /* Now check with serial number, subject and issuer specified */
3005     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3006      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3007     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3008     if (buf)
3009     {
3010         CERT_INFO *info = (CERT_INFO *)buf;
3011
3012         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3013         ok(info->SerialNumber.cbData == 1,
3014          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3015         ok(*info->SerialNumber.pbData == *serialNum,
3016          "Expected serial number %d, got %d\n", *serialNum,
3017          *info->SerialNumber.pbData);
3018         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3019          "Wrong size %d\n", info->Issuer.cbData);
3020         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3021          "Unexpected issuer\n");
3022         ok(info->Subject.cbData == sizeof(encodedCommonName),
3023          "Wrong size %d\n", info->Subject.cbData);
3024         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3025          info->Subject.cbData), "Unexpected subject\n");
3026         LocalFree(buf);
3027     }
3028     /* Check again with pub key specified */
3029     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3030      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3031      (BYTE *)&buf, &size);
3032     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3033     if (buf)
3034     {
3035         CERT_INFO *info = (CERT_INFO *)buf;
3036
3037         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3038         ok(info->SerialNumber.cbData == 1,
3039          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3040         ok(*info->SerialNumber.pbData == *serialNum,
3041          "Expected serial number %d, got %d\n", *serialNum,
3042          *info->SerialNumber.pbData);
3043         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3044          "Wrong size %d\n", info->Issuer.cbData);
3045         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3046          "Unexpected issuer\n");
3047         ok(info->Subject.cbData == sizeof(encodedCommonName),
3048          "Wrong size %d\n", info->Subject.cbData);
3049         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3050          info->Subject.cbData), "Unexpected subject\n");
3051         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3052          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3053          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3054         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3055          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3056         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3057          sizeof(aKey)), "Unexpected public key\n");
3058         LocalFree(buf);
3059     }
3060 }
3061
3062 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3063  0xe, 0xf };
3064
3065 static const BYTE signedBigCert[] = {
3066  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3067  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3068  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3069  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3070  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3071  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3072  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3073  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3074  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3075  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3076  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3077  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3078
3079 static void test_encodeCert(DWORD dwEncoding)
3080 {
3081     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3082      * also that bigCert is a NULL-terminated string, so don't count its
3083      * last byte (otherwise the signed cert won't decode.)
3084      */
3085     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3086      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3087     BOOL ret;
3088     BYTE *buf = NULL;
3089     DWORD bufSize = 0;
3090
3091     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3092      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3093     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3094     if (buf)
3095     {
3096         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3097         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3098         LocalFree(buf);
3099     }
3100 }
3101
3102 static void test_decodeCert(DWORD dwEncoding)
3103 {
3104     BOOL ret;
3105     BYTE *buf = NULL;
3106     DWORD size = 0;
3107
3108     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3109      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3110     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3111     if (buf)
3112     {
3113         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3114
3115         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3116          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3117         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3118          "Unexpected cert\n");
3119         ok(info->Signature.cbData == sizeof(hash),
3120          "Wrong signature size %d\n", info->Signature.cbData);
3121         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3122          "Unexpected signature\n");
3123         LocalFree(buf);
3124     }
3125     /* A signed cert decodes as a CERT_INFO too */
3126     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3127      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3128     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3129     if (buf)
3130     {
3131         CERT_INFO *info = (CERT_INFO *)buf;
3132
3133         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3134         ok(info->SerialNumber.cbData == 1,
3135          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3136         ok(*info->SerialNumber.pbData == *serialNum,
3137          "Expected serial number %d, got %d\n", *serialNum,
3138          *info->SerialNumber.pbData);
3139         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3140          "Wrong size %d\n", info->Issuer.cbData);
3141         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3142          "Unexpected issuer\n");
3143         ok(info->Subject.cbData == sizeof(encodedCommonName),
3144          "Wrong size %d\n", info->Subject.cbData);
3145         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3146          info->Subject.cbData), "Unexpected subject\n");
3147         LocalFree(buf);
3148     }
3149 }
3150
3151 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3152 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3153  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3154  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3155 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3156  0x00, 0x03 };
3157 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3158  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3159  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3160 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3161  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3162  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3163  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3164  0x2e, 0x6f, 0x72, 0x67 };
3165 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3166  CRL_REASON_AFFILIATION_CHANGED;
3167
3168 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3169 {
3170     CRL_DIST_POINTS_INFO info = { 0 };
3171     CRL_DIST_POINT point = { { 0 } };
3172     CERT_ALT_NAME_ENTRY entry = { 0 };
3173     BOOL ret;
3174     BYTE *buf = NULL;
3175     DWORD size = 0;
3176
3177     /* Test with an empty info */
3178     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3179      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3180     ok(!ret && GetLastError() == E_INVALIDARG,
3181      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3182     /* Test with one empty dist point */
3183     info.cDistPoint = 1;
3184     info.rgDistPoint = &point;
3185     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3186      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3187     if (buf)
3188     {
3189         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3190         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3191         LocalFree(buf);
3192     }
3193     /* A dist point with an invalid name */
3194     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3195     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3196     U(entry).pwszURL = (LPWSTR)nihongoURL;
3197     U(point.DistPointName).FullName.cAltEntry = 1;
3198     U(point.DistPointName).FullName.rgAltEntry = &entry;
3199     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3200      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3201     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3202      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3203     /* The first invalid character is at index 7 */
3204     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3205      "Expected invalid char at index 7, got %d\n",
3206      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3207     /* A dist point with (just) a valid name */
3208     U(entry).pwszURL = (LPWSTR)url;
3209     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3210      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3211     if (buf)
3212     {
3213         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3214         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3215         LocalFree(buf);
3216     }
3217     /* A dist point with (just) reason flags */
3218     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3219     point.ReasonFlags.cbData = sizeof(crlReason);
3220     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3221     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3222      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3223     if (buf)
3224     {
3225         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3226         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3227         LocalFree(buf);
3228     }
3229     /* A dist point with just an issuer */
3230     point.ReasonFlags.cbData = 0;
3231     point.CRLIssuer.cAltEntry = 1;
3232     point.CRLIssuer.rgAltEntry = &entry;
3233     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3234      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3235     if (buf)
3236     {
3237         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3238         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3239         LocalFree(buf);
3240     }
3241     /* A dist point with both a name and an issuer */
3242     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3243     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3244      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3245     if (buf)
3246     {
3247         ok(size == sizeof(distPointWithUrlAndIssuer),
3248          "Wrong size %d\n", size);
3249         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3250         LocalFree(buf);
3251     }
3252 }
3253
3254 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3255 {
3256     BOOL ret;
3257     BYTE *buf = NULL;
3258     DWORD size = 0;
3259     PCRL_DIST_POINTS_INFO info;
3260     PCRL_DIST_POINT point;
3261     PCERT_ALT_NAME_ENTRY entry;
3262
3263     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3264      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3265      (BYTE *)&buf, &size);
3266     if (ret)
3267     {
3268         info = (PCRL_DIST_POINTS_INFO)buf;
3269         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3270          "Wrong size %d\n", size);
3271         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3272          info->cDistPoint);
3273         point = info->rgDistPoint;
3274         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3275          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3276          point->DistPointName.dwDistPointNameChoice);
3277         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3278         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3279         LocalFree(buf);
3280     }
3281     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3282      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3283      (BYTE *)&buf, &size);
3284     if (ret)
3285     {
3286         info = (PCRL_DIST_POINTS_INFO)buf;
3287         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3288          "Wrong size %d\n", size);
3289         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3290          info->cDistPoint);
3291         point = info->rgDistPoint;
3292         ok(point->DistPointName.dwDistPointNameChoice ==
3293          CRL_DIST_POINT_FULL_NAME,
3294          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3295          point->DistPointName.dwDistPointNameChoice);
3296         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3297          "Expected 1 name entry, got %d\n",
3298          U(point->DistPointName).FullName.cAltEntry);
3299         entry = U(point->DistPointName).FullName.rgAltEntry;
3300         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3301          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3302         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3303         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3304         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3305         LocalFree(buf);
3306     }
3307     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3308      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3309      NULL, (BYTE *)&buf, &size);
3310     if (ret)
3311     {
3312         info = (PCRL_DIST_POINTS_INFO)buf;
3313         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3314          "Wrong size %d\n", size);
3315         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3316          info->cDistPoint);
3317         point = info->rgDistPoint;
3318         ok(point->DistPointName.dwDistPointNameChoice ==
3319          CRL_DIST_POINT_NO_NAME,
3320          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3321          point->DistPointName.dwDistPointNameChoice);
3322         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3323          "Expected reason length\n");
3324         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3325          "Unexpected reason\n");
3326         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3327         LocalFree(buf);
3328     }
3329     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3330      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3331      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3332     if (ret)
3333     {
3334         info = (PCRL_DIST_POINTS_INFO)buf;
3335         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3336          "Wrong size %d\n", size);
3337         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3338          info->cDistPoint);
3339         point = info->rgDistPoint;
3340         ok(point->DistPointName.dwDistPointNameChoice ==
3341          CRL_DIST_POINT_FULL_NAME,
3342          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3343          point->DistPointName.dwDistPointNameChoice);
3344         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3345          "Expected 1 name entry, got %d\n",
3346          U(point->DistPointName).FullName.cAltEntry);
3347         entry = U(point->DistPointName).FullName.rgAltEntry;
3348         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3349          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3350         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3351         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3352         ok(point->CRLIssuer.cAltEntry == 1,
3353          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3354         entry = point->CRLIssuer.rgAltEntry;
3355         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3356          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3357         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3358         LocalFree(buf);
3359     }
3360 }
3361
3362 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3363 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3364 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3365  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3366  0x67 };
3367
3368 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3369 {
3370     BOOL ret;
3371     BYTE *buf = NULL;
3372     DWORD size = 0;
3373     CRL_ISSUING_DIST_POINT point = { { 0 } };
3374     CERT_ALT_NAME_ENTRY entry;
3375
3376     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3377      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3378     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3379     {
3380         skip("no X509_ISSUING_DIST_POINT encode support\n");
3381         return;
3382     }
3383     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3384      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3385     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3386      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3387     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3388     if (buf)
3389     {
3390         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3391         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3392         LocalFree(buf);
3393     }
3394     /* nonsensical flags */
3395     point.fOnlyContainsUserCerts = TRUE;
3396     point.fOnlyContainsCACerts = TRUE;
3397     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3398      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3399     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3400     if (buf)
3401     {
3402         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3403         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3404         LocalFree(buf);
3405     }
3406     /* unimplemented name type */
3407     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3408     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3409     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3410      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3411     ok(!ret && GetLastError() == E_INVALIDARG,
3412      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3413     /* empty name */
3414     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3415     U(point.DistPointName).FullName.cAltEntry = 0;
3416     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3417      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3418     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3419     if (buf)
3420     {
3421         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3422         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3423         LocalFree(buf);
3424     }
3425     /* name with URL entry */
3426     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3427     U(entry).pwszURL = (LPWSTR)url;
3428     U(point.DistPointName).FullName.cAltEntry = 1;
3429     U(point.DistPointName).FullName.rgAltEntry = &entry;
3430     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3431      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3432     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3433     if (buf)
3434     {
3435         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3436         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3437         LocalFree(buf);
3438     }
3439 }
3440
3441 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3442  const CERT_ALT_NAME_ENTRY *got)
3443 {
3444     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3445      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3446      got->dwAltNameChoice);
3447     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3448     {
3449         switch (got->dwAltNameChoice)
3450         {
3451         case CERT_ALT_NAME_RFC822_NAME:
3452         case CERT_ALT_NAME_DNS_NAME:
3453         case CERT_ALT_NAME_EDI_PARTY_NAME:
3454         case CERT_ALT_NAME_URL:
3455         case CERT_ALT_NAME_REGISTERED_ID:
3456             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3457              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3458              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3459              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3460              "Unexpected name\n");
3461             break;
3462         case CERT_ALT_NAME_X400_ADDRESS:
3463         case CERT_ALT_NAME_DIRECTORY_NAME:
3464         case CERT_ALT_NAME_IP_ADDRESS:
3465             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3466                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3467             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3468                        U(*got).IPAddress.cbData), "Unexpected value\n");
3469             break;
3470         }
3471     }
3472 }
3473
3474 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3475  const CERT_ALT_NAME_INFO *got)
3476 {
3477     DWORD i;
3478
3479     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3480      expected->cAltEntry, got->cAltEntry);
3481     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3482         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3483 }
3484
3485 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3486  const CRL_DIST_POINT_NAME *got)
3487 {
3488     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3489      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3490     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3491         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3492 }
3493
3494 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3495  const CRL_ISSUING_DIST_POINT *got)
3496 {
3497     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3498     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3499      "Unexpected fOnlyContainsUserCerts\n");
3500     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3501      "Unexpected fOnlyContainsCACerts\n");
3502     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3503      "Unexpected reason flags\n");
3504     ok(got->fIndirectCRL == expected->fIndirectCRL,
3505      "Unexpected fIndirectCRL\n");
3506 }
3507
3508 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3509 {
3510     BOOL ret;
3511     BYTE *buf = NULL;
3512     DWORD size = 0;
3513     CRL_ISSUING_DIST_POINT point = { { 0 } };
3514
3515     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3516      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3517      (BYTE *)&buf, &size);
3518     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3519     {
3520         skip("no X509_ISSUING_DIST_POINT decode support\n");
3521         return;
3522     }
3523     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3524     if (ret)
3525     {
3526         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3527         LocalFree(buf);
3528     }
3529     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3530      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3531      (BYTE *)&buf, &size);
3532     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3533     if (ret)
3534     {
3535         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3536         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3537         LocalFree(buf);
3538     }
3539     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3540      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3541      (BYTE *)&buf, &size);
3542     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3543     if (ret)
3544     {
3545         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3546         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3547         U(point.DistPointName).FullName.cAltEntry = 0;
3548         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3549         LocalFree(buf);
3550     }
3551     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3552      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3553     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3554     if (ret)
3555     {
3556         CERT_ALT_NAME_ENTRY entry;
3557
3558         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3559         U(entry).pwszURL = (LPWSTR)url;
3560         U(point.DistPointName).FullName.cAltEntry = 1;
3561         U(point.DistPointName).FullName.rgAltEntry = &entry;
3562         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3563         LocalFree(buf);
3564     }
3565 }
3566
3567 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3568  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3569  0x30, 0x5a };
3570 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3571  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3572  0x30, 0x30, 0x30, 0x30, 0x5a };
3573 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3574  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3575  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3576  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3577  0x5a };
3578 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3579  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3580  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3581  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3582  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3583  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3584 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3585  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3586  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3587  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3588  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3589  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3590 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3591  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3592  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3593  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3594  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3595  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3596  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3597 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3598  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3599  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3600  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3601  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3602  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3603  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3604 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3605  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3606  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3607  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3608  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3609  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3610  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3611 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3612  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3613  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3614  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3615  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3616  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3617  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3618
3619 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3620 {
3621     BOOL ret;
3622     BYTE *buf = NULL;
3623     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3624     DWORD size = 0;
3625     CRL_INFO info = { 0 };
3626     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3627     CERT_EXTENSION ext;
3628
3629     /* Test with a V1 CRL */
3630     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3631      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3632     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3633      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3634     if (buf)
3635     {
3636         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3637         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3638         LocalFree(buf);
3639     }
3640     /* Test v2 CRL */
3641     info.dwVersion = CRL_V2;
3642     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3643      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3644     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3645      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3646     if (buf)
3647     {
3648         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3649          v2CRL[1] + 2, size);
3650         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3651         LocalFree(buf);
3652     }
3653     /* v1 CRL with a name */
3654     info.dwVersion = CRL_V1;
3655     info.Issuer.cbData = sizeof(encodedCommonName);
3656     info.Issuer.pbData = (BYTE *)encodedCommonName;
3657     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3658      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3659     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3660     if (buf)
3661     {
3662         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3663         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3664         LocalFree(buf);
3665     }
3666     if (0)
3667     {
3668         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3669         info.cCRLEntry = 1;
3670         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3671          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3672         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3673          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3674     }
3675     /* now set an empty entry */
3676     info.cCRLEntry = 1;
3677     info.rgCRLEntry = &entry;
3678     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3679      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3680     if (buf)
3681     {
3682         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3683          "Wrong size %d\n", size);
3684         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3685          "Got unexpected value\n");
3686         LocalFree(buf);
3687     }
3688     /* an entry with a serial number */
3689     entry.SerialNumber.cbData = sizeof(serialNum);
3690     entry.SerialNumber.pbData = (BYTE *)serialNum;
3691     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3692      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3693     if (buf)
3694     {
3695         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3696          "Wrong size %d\n", size);
3697         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3698          "Got unexpected value\n");
3699         LocalFree(buf);
3700     }
3701     /* an entry with an extension */
3702     entry.cExtension = 1;
3703     entry.rgExtension = &criticalExt;
3704     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3705      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3706     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3707     if (buf)
3708     {
3709         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3710         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3711         LocalFree(buf);
3712     }
3713     /* a CRL with an extension */
3714     entry.cExtension = 0;
3715     info.cExtension = 1;
3716     info.rgExtension = &criticalExt;
3717     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3718      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3719     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3720     if (buf)
3721     {
3722         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3723         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3724         LocalFree(buf);
3725     }
3726     /* a v2 CRL with an extension, this time non-critical */
3727     info.dwVersion = CRL_V2;
3728     info.rgExtension = &nonCriticalExt;
3729     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3730      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3731     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3732     if (buf)
3733     {
3734         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3735         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3736         LocalFree(buf);
3737     }
3738     /* a v2 CRL with an issuing dist point extension */
3739     ext.pszObjId = oid_issuing_dist_point;
3740     ext.fCritical = TRUE;
3741     ext.Value.cbData = sizeof(urlIDP);
3742     ext.Value.pbData = (LPBYTE)urlIDP;
3743     entry.rgExtension = &ext;
3744     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3745      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3746     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3747     if (buf)
3748     {
3749         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3750         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3751         LocalFree(buf);
3752     }
3753 }
3754
3755 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3756  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3757  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3758  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3759  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3760  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3761  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3762  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3763  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3764  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3765  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3766  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3767  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3768  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3769  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3770  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3771  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3772  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3773  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3774  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3775  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3776  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3777  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3778  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3779  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3780  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3781  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3782  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3783  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3784  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3785  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3786  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3787  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3788  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3789  0xcd };
3790 static const BYTE verisignCRLWithLotsOfEntries[] = {
3791 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3792 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3793 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3794 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3795 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3796 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3797 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3798 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3799 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3800 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3801 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3802 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3803 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3804 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3805 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3806 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3807 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3808 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3809 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3810 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3811 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3812 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3813 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3814 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3815 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3816 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3817 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3818 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3819 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3820 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3821 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3822 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3823 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3824 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3825 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3826 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3827 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3828 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3829 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3830 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3831 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3832 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3833 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3834 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3835 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3836 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3837 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3838 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3839 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3840 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3841 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3842 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3843 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3844 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3845 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3846 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3847 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3848 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3849 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3850 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3851 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3852 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3853 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3854 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3855 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3856 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3857 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3858 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3859 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3860 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3861 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3862 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3863 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3864 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3865 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3866 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3867 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3868 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3869 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3870 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3871 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3872 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3873 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3874 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3875 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3876 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3877 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3878 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3879 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3880 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3881 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3882 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3883 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3884 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3885 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3886 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3887 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3888 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3889 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3890 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3891 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3892 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3893 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3894 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3895 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3896 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3897 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3898 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3899 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3900 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3901 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3902 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3903 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3904 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3905 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3906 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3907 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3908 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3909 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3910 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3911 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3912 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3913 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3914 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3915 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3916 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3917 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3918 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3919 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3920 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3921 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3922 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3923 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3924 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3925 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3926 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3927 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3928 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3929 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3930 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3931 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3932 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3933 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3934 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3935 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3936 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3937 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3938 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3939 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3940 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3941 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3942 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3943 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3944 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3945 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3946 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3947 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3948 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3949 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3950 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3951 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3952 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3953 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3954 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3955 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3956 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3957 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3958 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3959 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3960 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3961 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3962 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3963 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3964 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3965 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3966 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3967 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3968 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3969 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3970 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3971 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3972 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3973 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3974 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3975 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3976 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3977 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3978 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3979 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3980 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3981 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3982 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3983 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3984 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3985 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3986 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3987 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3988 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3989 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3990 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3991 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3992 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3993 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3994 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3995 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3996 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3997 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3998 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3999 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4000 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4001 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4002 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4003 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4004 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4005 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4006 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4007 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4008 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4009 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4010 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4011 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4012 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4013 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4014 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4015 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4016 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4017 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4018 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4019 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4020 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4021 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4022 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4023 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4024 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4025 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4026 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4027 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4028 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4029 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4030 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4031 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4032 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4033 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4034 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4035 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4036 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4037 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4038 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4039 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4040 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4041 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4042 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4043 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4044 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4045 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4046 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4047 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4048 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4049 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4050 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4051 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4052 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4053 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4054 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4055 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4056 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4057 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4058 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4059 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4060 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4061 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4062 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4063 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4064 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4065 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4066 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4067 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4068 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4069 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4070 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4071 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4072 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4073 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4074 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4075 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4076 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4077 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4078 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4079 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4080 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4081 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4082 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4083 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4084 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4085 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4086 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4087 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4088 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4089 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4090 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4091 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4092 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4093 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4094 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4095 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4096 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4097 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4098 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4099 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4100 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4101 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4102 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4103 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4104 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4105 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4106 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4107 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4108 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4109 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4110 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4111 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4112 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4113 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4114 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4115 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4116 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4117 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4118 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4119 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4120 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4121 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4122 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4123 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4124 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4125 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4126 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4127 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4128 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4129 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4130 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4131 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4132 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4133 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4134 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4135 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4136 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4137 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4138 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4139 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4140 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4141 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4142 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4143 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4144 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4145 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4146 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4147 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4148 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4149 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4150 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4151 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4152 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4153 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4154 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4155 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4156 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4157 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4158 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4159 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4160 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4161 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4162 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4163 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4164 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4165 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4166 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4167 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4168 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4169 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4170 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4171 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4172 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4173 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4174 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4175 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4176 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4177 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4178 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4179 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4180 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4181 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4182 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4183 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4184 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4185 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4186 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4187 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4188 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4189 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4190 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4191 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4192 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4193 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4194 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4195 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4196 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4197 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4198 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4199 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4200 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4201 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4202 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4203 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4204 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4205 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4206 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4207 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4208 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4209 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4210 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4211 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4212 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4213 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4214 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4215 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4216 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4217 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4218 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4219 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4220 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4221 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4222 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4223 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4224 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4225 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4226 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4227 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4228 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4229 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4230 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4231 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4232 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4233 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4234 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4235 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4236 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4237 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4238 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4239 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4240 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4241 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4242 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4243 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4244 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4245 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4246 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4247 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4248 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4249 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4250 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4251 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4252 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4253 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4254 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4255 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4256 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4257 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4258 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4259 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4260 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4261 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4262 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4263 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4264 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4265 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4266 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4267 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4268 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4269 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4270 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4271 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4272 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4273 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4274 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4275 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4276 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4277 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4278 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4279 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4280 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4281 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4282 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4283 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4284 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4285 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4286 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4287 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4288 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4289 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4290 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4291 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4292 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4293 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4294 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4295 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4296 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4297 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4298 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4299
4300 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4301 {
4302     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4303     BOOL ret;
4304     BYTE *buf = NULL;
4305     DWORD size = 0, i;
4306
4307     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4308     {
4309         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4310          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4311          (BYTE *)&buf, &size);
4312         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4313          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4314          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4315          GetLastError());
4316     }
4317     /* at a minimum, a CRL must contain an issuer: */
4318     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4319      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4320      (BYTE *)&buf, &size);
4321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4322     if (buf)
4323     {
4324         CRL_INFO *info = (CRL_INFO *)buf;
4325
4326         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4327         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4328          info->cCRLEntry);
4329         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4330          "Wrong issuer size %d\n", info->Issuer.cbData);
4331         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4332          "Unexpected issuer\n");
4333         LocalFree(buf);
4334     }
4335     /* check decoding with an empty CRL entry */
4336     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4337      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4338      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4339     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4340      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4341      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4342      GetLastError());
4343     /* with a real CRL entry */
4344     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4345      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4346      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4347     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4348     if (buf)
4349     {
4350         CRL_INFO *info = (CRL_INFO *)buf;
4351         CRL_ENTRY *entry;
4352
4353         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4354         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4355          info->cCRLEntry);
4356         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4357         entry = info->rgCRLEntry;
4358         ok(entry->SerialNumber.cbData == 1,
4359          "Expected serial number size 1, got %d\n",
4360          entry->SerialNumber.cbData);
4361         ok(*entry->SerialNumber.pbData == *serialNum,
4362          "Expected serial number %d, got %d\n", *serialNum,
4363          *entry->SerialNumber.pbData);
4364         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4365          "Wrong issuer size %d\n", info->Issuer.cbData);
4366         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4367          "Unexpected issuer\n");
4368         LocalFree(buf);
4369     }
4370     /* a real CRL from verisign that has extensions */
4371     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4372      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4373      NULL, (BYTE *)&buf, &size);
4374     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4375     if (buf)
4376     {
4377         CRL_INFO *info = (CRL_INFO *)buf;
4378         CRL_ENTRY *entry;
4379
4380         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4381         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4382          info->cCRLEntry);
4383         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4384         entry = info->rgCRLEntry;
4385         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4386          info->cExtension);
4387         LocalFree(buf);
4388     }
4389     /* another real CRL from verisign that has lots of entries */
4390     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4391      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4392      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4393     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4394     if (buf)
4395     {
4396         CRL_INFO *info = (CRL_INFO *)buf;
4397
4398         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4399         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4400          info->cCRLEntry);
4401         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4402          info->cExtension);
4403         LocalFree(buf);
4404     }
4405     /* and finally, with an extension */
4406     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4407      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4408      NULL, (BYTE *)&buf, &size);
4409     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4410     if (buf)
4411     {
4412         CRL_INFO *info = (CRL_INFO *)buf;
4413         CRL_ENTRY *entry;
4414
4415         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4416         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4417          info->cCRLEntry);
4418         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4419         entry = info->rgCRLEntry;
4420         ok(entry->SerialNumber.cbData == 1,
4421          "Expected serial number size 1, got %d\n",
4422          entry->SerialNumber.cbData);
4423         ok(*entry->SerialNumber.pbData == *serialNum,
4424          "Expected serial number %d, got %d\n", *serialNum,
4425          *entry->SerialNumber.pbData);
4426         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4427          "Wrong issuer size %d\n", info->Issuer.cbData);
4428         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4429          "Unexpected issuer\n");
4430         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4431          info->cExtension);
4432         LocalFree(buf);
4433     }
4434     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4435      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4436      NULL, (BYTE *)&buf, &size);
4437     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4438     if (buf)
4439     {
4440         CRL_INFO *info = (CRL_INFO *)buf;
4441
4442         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4443          info->cExtension);
4444         LocalFree(buf);
4445     }
4446     /* And again, with an issuing dist point */
4447     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4448      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4449      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4450     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4451     if (buf)
4452     {
4453         CRL_INFO *info = (CRL_INFO *)buf;
4454
4455         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4456          info->cExtension);
4457         LocalFree(buf);
4458     }
4459 }
4460
4461 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4462  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4463 static const BYTE encodedUsage[] = {
4464  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4465  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4466  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4467
4468 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4469 {
4470     BOOL ret;
4471     BYTE *buf = NULL;
4472     DWORD size = 0;
4473     CERT_ENHKEY_USAGE usage;
4474
4475     /* Test with empty usage */
4476     usage.cUsageIdentifier = 0;
4477     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4478      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4479     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4480     if (buf)
4481     {
4482         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4483         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4484         LocalFree(buf);
4485     }
4486     /* Test with a few usages */
4487     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4488     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4489     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4490      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4491     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4492     if (buf)
4493     {
4494         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4495         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4496         LocalFree(buf);
4497     }
4498 }
4499
4500 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4501 {
4502     BOOL ret;
4503     LPBYTE buf = NULL;
4504     DWORD size = 0;
4505
4506     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4507      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4508      (BYTE *)&buf, &size);
4509     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4510     if (buf)
4511     {
4512         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4513
4514         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4515          "Wrong size %d\n", size);
4516         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4517          usage->cUsageIdentifier);
4518         LocalFree(buf);
4519     }
4520     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4521      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4522      (BYTE *)&buf, &size);
4523     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4524     if (buf)
4525     {
4526         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4527         DWORD i;
4528
4529         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4530          "Wrong size %d\n", size);
4531         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4532          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4533         for (i = 0; i < usage->cUsageIdentifier; i++)
4534             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4535              "Expected OID %s, got %s\n", keyUsages[i],
4536              usage->rgpszUsageIdentifier[i]);
4537         LocalFree(buf);
4538     }
4539 }
4540
4541 static BYTE keyId[] = { 1,2,3,4 };
4542 static const BYTE authorityKeyIdWithId[] = {
4543  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4544 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4545  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4546  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4547 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4548
4549 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4550 {
4551     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4552     BOOL ret;
4553     BYTE *buf = NULL;
4554     DWORD size = 0;
4555
4556     /* Test with empty id */
4557     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4558      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4559     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4560     if (buf)
4561     {
4562         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4563         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4564         LocalFree(buf);
4565     }
4566     /* With just a key id */
4567     info.KeyId.cbData = sizeof(keyId);
4568     info.KeyId.pbData = keyId;
4569     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4570      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4571     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4572     if (buf)
4573     {
4574         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4575         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4576         LocalFree(buf);
4577     }
4578     /* With just an issuer */
4579     info.KeyId.cbData = 0;
4580     info.CertIssuer.cbData = sizeof(encodedCommonName);
4581     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4582     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4583      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4584     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4585     if (buf)
4586     {
4587         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4588          size);
4589         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4590         LocalFree(buf);
4591     }
4592     /* With just a serial number */
4593     info.CertIssuer.cbData = 0;
4594     info.CertSerialNumber.cbData = sizeof(serialNum);
4595     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4596     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4597      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4598     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4599     if (buf)
4600     {
4601         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4602          size);
4603         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4604         LocalFree(buf);
4605     }
4606 }
4607
4608 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4609 {
4610     BOOL ret;
4611     LPBYTE buf = NULL;
4612     DWORD size = 0;
4613
4614     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4615      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4616      (BYTE *)&buf, &size);
4617     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4618     if (buf)
4619     {
4620         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4621
4622         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4623          size);
4624         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4625         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4626         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4627         LocalFree(buf);
4628     }
4629     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4630      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4631      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4632     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4633     if (buf)
4634     {
4635         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4636
4637         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4638          size);
4639         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4640         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4641          "Unexpected key id\n");
4642         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4643         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4644         LocalFree(buf);
4645     }
4646     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4647      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4648      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4649     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4650     if (buf)
4651     {
4652         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4653
4654         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4655          size);
4656         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4657         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4658          "Unexpected issuer len\n");
4659         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4660          sizeof(encodedCommonName)), "Unexpected issuer\n");
4661         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4662         LocalFree(buf);
4663     }
4664     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4665      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4666      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4667     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4668     if (buf)
4669     {
4670         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4671
4672         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4673          size);
4674         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4675         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4676         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4677          "Unexpected serial number len\n");
4678         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4679          "Unexpected serial number\n");
4680         LocalFree(buf);
4681     }
4682 }
4683
4684 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4685  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4686  0x6f,0x72,0x67 };
4687
4688 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4689 {
4690     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4691     CERT_ALT_NAME_ENTRY entry = { 0 };
4692     BOOL ret;
4693     BYTE *buf = NULL;
4694     DWORD size = 0;
4695
4696     /* Test with empty id */
4697     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4698      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4699     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4700     if (buf)
4701     {
4702         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4703         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4704         LocalFree(buf);
4705     }
4706     /* With just a key id */
4707     info.KeyId.cbData = sizeof(keyId);
4708     info.KeyId.pbData = keyId;
4709     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4710      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4711     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4712     if (buf)
4713     {
4714         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4715          size);
4716         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4717         LocalFree(buf);
4718     }
4719     /* With a bogus issuer name */
4720     info.KeyId.cbData = 0;
4721     info.AuthorityCertIssuer.cAltEntry = 1;
4722     info.AuthorityCertIssuer.rgAltEntry = &entry;
4723     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4724      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4725     ok(!ret && GetLastError() == E_INVALIDARG,
4726      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4727     /* With an issuer name */
4728     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4729     U(entry).pwszURL = (LPWSTR)url;
4730     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4731      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4732     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4733     if (buf)
4734     {
4735         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4736          size);
4737         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4738          "Unexpected value\n");
4739         LocalFree(buf);
4740     }
4741     /* With just a serial number */
4742     info.AuthorityCertIssuer.cAltEntry = 0;
4743     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4744     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4745     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4746      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4747     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4748     if (buf)
4749     {
4750         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4751          size);
4752         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4753         LocalFree(buf);
4754     }
4755 }
4756
4757 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4758 {
4759     BOOL ret;
4760     LPBYTE buf = NULL;
4761     DWORD size = 0;
4762
4763     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4764      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4765      (BYTE *)&buf, &size);
4766     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4767     if (buf)
4768     {
4769         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4770
4771         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4772          size);
4773         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4774         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4775          "Expected no issuer name entries\n");
4776         ok(info->AuthorityCertSerialNumber.cbData == 0,
4777          "Expected no serial number\n");
4778         LocalFree(buf);
4779     }
4780     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4781      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4782      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4783     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4784     if (buf)
4785     {
4786         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4787
4788         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4789          size);
4790         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4791         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4792          "Unexpected key id\n");
4793         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4794          "Expected no issuer name entries\n");
4795         ok(info->AuthorityCertSerialNumber.cbData == 0,
4796          "Expected no serial number\n");
4797         LocalFree(buf);
4798     }
4799     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4800      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4801      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4802     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4803     if (buf)
4804     {
4805         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4806
4807         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4808          size);
4809         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4810         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4811          "Expected 1 issuer entry, got %d\n",
4812          info->AuthorityCertIssuer.cAltEntry);
4813         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4814          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4815          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4816         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4817          url), "Unexpected URL\n");
4818         ok(info->AuthorityCertSerialNumber.cbData == 0,
4819          "Expected no serial number\n");
4820         LocalFree(buf);
4821     }
4822     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4823      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4824      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4825     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4826     if (buf)
4827     {
4828         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4829
4830         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4831          size);
4832         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4833         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4834          "Expected no issuer name entries\n");
4835         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4836          "Unexpected serial number len\n");
4837         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4838          sizeof(serialNum)), "Unexpected serial number\n");
4839         LocalFree(buf);
4840     }
4841 }
4842
4843 static const BYTE authorityInfoAccessWithUrl[] = {
4844 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4845 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4846 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4847 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4848 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4849 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4850
4851 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4852 {
4853     static char oid1[] = "1.2.3";
4854     static char oid2[] = "1.5.6";
4855     BOOL ret;
4856     BYTE *buf = NULL;
4857     DWORD size = 0;
4858     CERT_ACCESS_DESCRIPTION accessDescription[2];
4859     CERT_AUTHORITY_INFO_ACCESS aia;
4860
4861     memset(accessDescription, 0, sizeof(accessDescription));
4862     aia.cAccDescr = 0;
4863     aia.rgAccDescr = NULL;
4864     /* Having no access descriptions is allowed */
4865     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4866      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4867     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4868     if (buf)
4869     {
4870         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4871         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4872         LocalFree(buf);
4873         buf = NULL;
4874     }
4875     /* It can't have an empty access method */
4876     aia.cAccDescr = 1;
4877     aia.rgAccDescr = accessDescription;
4878     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4879      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4880     ok(!ret && (GetLastError() == E_INVALIDARG ||
4881      GetLastError() == OSS_LIMITED /* Win9x */),
4882      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4883     /* It can't have an empty location */
4884     accessDescription[0].pszAccessMethod = oid1;
4885     SetLastError(0xdeadbeef);
4886     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4887      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4888     ok(!ret && GetLastError() == E_INVALIDARG,
4889      "expected E_INVALIDARG, got %08x\n", GetLastError());
4890     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4891     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4892     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4893      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4894     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4895     if (buf)
4896     {
4897         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4898          size);
4899         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4900          "unexpected value\n");
4901         LocalFree(buf);
4902         buf = NULL;
4903     }
4904     accessDescription[1].pszAccessMethod = oid2;
4905     accessDescription[1].AccessLocation.dwAltNameChoice =
4906      CERT_ALT_NAME_IP_ADDRESS;
4907     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4908      sizeof(encodedIPAddr);
4909     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4910      (LPBYTE)encodedIPAddr;
4911     aia.cAccDescr = 2;
4912     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4913      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4914     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4915     if (buf)
4916     {
4917         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4918          "unexpected size %d\n", size);
4919         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4920          "unexpected value\n");
4921         LocalFree(buf);
4922         buf = NULL;
4923     }
4924 }
4925
4926 static void compareAuthorityInfoAccess(LPCSTR header,
4927  const CERT_AUTHORITY_INFO_ACCESS *expected,
4928  const CERT_AUTHORITY_INFO_ACCESS *got)
4929 {
4930     DWORD i;
4931
4932     ok(expected->cAccDescr == got->cAccDescr,
4933      "%s: expected %d access descriptions, got %d\n", header,
4934      expected->cAccDescr, got->cAccDescr);
4935     for (i = 0; i < expected->cAccDescr; i++)
4936     {
4937         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4938          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4939          header, i, expected->rgAccDescr[i].pszAccessMethod,
4940          got->rgAccDescr[i].pszAccessMethod);
4941         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4942          &got->rgAccDescr[i].AccessLocation);
4943     }
4944 }
4945
4946 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4947 {
4948     static char oid1[] = "1.2.3";
4949     static char oid2[] = "1.5.6";
4950     BOOL ret;
4951     LPBYTE buf = NULL;
4952     DWORD size = 0;
4953
4954     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4955      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4956      (BYTE *)&buf, &size);
4957     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4958     if (buf)
4959     {
4960         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4961
4962         compareAuthorityInfoAccess("empty AIA", &aia,
4963          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4964         LocalFree(buf);
4965         buf = NULL;
4966     }
4967     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4968      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4969      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4970     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4971     if (buf)
4972     {
4973         CERT_ACCESS_DESCRIPTION accessDescription;
4974         CERT_AUTHORITY_INFO_ACCESS aia;
4975
4976         accessDescription.pszAccessMethod = oid1;
4977         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4978         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
4979         aia.cAccDescr = 1;
4980         aia.rgAccDescr = &accessDescription;
4981         compareAuthorityInfoAccess("AIA with URL", &aia,
4982          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4983         LocalFree(buf);
4984         buf = NULL;
4985     }
4986     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4987      authorityInfoAccessWithUrlAndIPAddr,
4988      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
4989      NULL, (BYTE *)&buf, &size);
4990     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4991     if (buf)
4992     {
4993         CERT_ACCESS_DESCRIPTION accessDescription[2];
4994         CERT_AUTHORITY_INFO_ACCESS aia;
4995
4996         accessDescription[0].pszAccessMethod = oid1;
4997         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4998         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4999         accessDescription[1].pszAccessMethod = oid2;
5000         accessDescription[1].AccessLocation.dwAltNameChoice =
5001          CERT_ALT_NAME_IP_ADDRESS;
5002         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5003          sizeof(encodedIPAddr);
5004         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5005          (LPBYTE)encodedIPAddr;
5006         aia.cAccDescr = 2;
5007         aia.rgAccDescr = accessDescription;
5008         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5009          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5010         LocalFree(buf);
5011         buf = NULL;
5012     }
5013 }
5014
5015 static const BYTE emptyCTL[] = {
5016 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5017 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5018 static const BYTE emptyCTLWithVersion1[] = {
5019 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5020 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5021 static const BYTE ctlWithUsageIdentifier[] = {
5022 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5023 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5024 static const BYTE ctlWithListIdentifier[] = {
5025 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5026 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5027 static const BYTE ctlWithSequenceNumber[] = {
5028 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,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 ctlWithThisUpdate[] = {
5031 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5032 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5033 static const BYTE ctlWithThisAndNextUpdate[] = {
5034 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5035 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5036 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5037 static const BYTE ctlWithAlgId[] = {
5038 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5039 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5040 static const BYTE ctlWithBogusEntry[] = {
5041 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5042 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5043 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5044 static const BYTE ctlWithOneEntry[] = {
5045 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5046 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5047 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5048 static const BYTE ctlWithTwoEntries[] = {
5049 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5050 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5051 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5052 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5053 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5054
5055 static void test_encodeCTL(DWORD dwEncoding)
5056 {
5057     static char oid1[] = "1.2.3";
5058     static char oid2[] = "1.5.6";
5059     char *pOid1 = oid1;
5060     BOOL ret;
5061     BYTE *buf = NULL;
5062     DWORD size = 0;
5063     CTL_INFO info;
5064     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5065     CTL_ENTRY ctlEntry[2];
5066     CRYPT_ATTRIBUTE attr1, attr2;
5067     CRYPT_ATTR_BLOB value1, value2;
5068
5069     memset(&info, 0, sizeof(info));
5070     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5071      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5072     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5073     if (buf)
5074     {
5075         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5076         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5077         LocalFree(buf);
5078         buf = NULL;
5079     }
5080     info.dwVersion = 1;
5081     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5082      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5083     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5084     if (buf)
5085     {
5086         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5087         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5088         LocalFree(buf);
5089         buf = NULL;
5090     }
5091     info.dwVersion = 0;
5092     info.SubjectUsage.cUsageIdentifier = 1;
5093     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5094     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5095      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5096     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5097     if (buf)
5098     {
5099         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5100          size);
5101         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5102         LocalFree(buf);
5103         buf = NULL;
5104     }
5105     info.SubjectUsage.cUsageIdentifier = 0;
5106     info.ListIdentifier.cbData = sizeof(serialNum);
5107     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5108     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5109      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5110     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5111     if (buf)
5112     {
5113         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5114         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5115         LocalFree(buf);
5116         buf = NULL;
5117     }
5118     info.ListIdentifier.cbData = 0;
5119     info.SequenceNumber.cbData = sizeof(serialNum);
5120     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5121     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5122      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5123     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5124     if (buf)
5125     {
5126         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5127          size);
5128         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5129         LocalFree(buf);
5130         buf = NULL;
5131     }
5132     info.SequenceNumber.cbData = 0;
5133     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5134     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5135      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5136     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5137     if (buf)
5138     {
5139         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5140         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5141         LocalFree(buf);
5142         buf = NULL;
5143     }
5144     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5145     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5146      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5147     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5148     if (buf)
5149     {
5150         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5151          size);
5152         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5153         LocalFree(buf);
5154         buf = NULL;
5155     }
5156     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5157     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5158     info.SubjectAlgorithm.pszObjId = oid2;
5159     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5160      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5161     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5162     if (buf)
5163     {
5164         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5165         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5166         LocalFree(buf);
5167         buf = NULL;
5168     }
5169     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5170      * (see tests below) but it'll encode fine.
5171      */
5172     info.SubjectAlgorithm.pszObjId = NULL;
5173     value1.cbData = sizeof(serialNum);
5174     value1.pbData = (LPBYTE)serialNum;
5175     attr1.pszObjId = oid1;
5176     attr1.cValue = 1;
5177     attr1.rgValue = &value1;
5178     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5179     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5180     ctlEntry[0].cAttribute = 1;
5181     ctlEntry[0].rgAttribute = &attr1;
5182     info.cCTLEntry = 1;
5183     info.rgCTLEntry = ctlEntry;
5184     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5185      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5186     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5187     if (buf)
5188     {
5189         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5190         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5191         LocalFree(buf);
5192         buf = NULL;
5193     }
5194     value1.cbData = sizeof(emptySequence);
5195     value1.pbData = (LPBYTE)emptySequence;
5196     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5197      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5198     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5199     if (buf)
5200     {
5201         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5202         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5203         LocalFree(buf);
5204         buf = NULL;
5205     }
5206     value2.cbData = sizeof(encodedIPAddr);
5207     value2.pbData = (LPBYTE)encodedIPAddr;
5208     attr2.pszObjId = oid2;
5209     attr2.cValue = 1;
5210     attr2.rgValue = &value2;
5211     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5212     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5213     ctlEntry[1].cAttribute = 1;
5214     ctlEntry[1].rgAttribute = &attr2;
5215     info.cCTLEntry = 2;
5216     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5217      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5218     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5219     if (buf)
5220     {
5221         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5222         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5223         LocalFree(buf);
5224         buf = NULL;
5225     }
5226 }
5227
5228 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5229  const CTL_INFO *got)
5230 {
5231     DWORD i, j, k;
5232
5233     ok(expected->dwVersion == got->dwVersion,
5234      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5235      got->dwVersion);
5236     ok(expected->SubjectUsage.cUsageIdentifier ==
5237      got->SubjectUsage.cUsageIdentifier,
5238      "%s: expected %d usage identifiers, got %d\n", header,
5239      expected->SubjectUsage.cUsageIdentifier,
5240      got->SubjectUsage.cUsageIdentifier);
5241     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5242         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5243          got->SubjectUsage.rgpszUsageIdentifier[i]),
5244          "%s[%d]: expected %s, got %s\n", header, i,
5245          expected->SubjectUsage.rgpszUsageIdentifier[i],
5246          got->SubjectUsage.rgpszUsageIdentifier[i]);
5247     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5248      "%s: expected list identifier of %d bytes, got %d\n", header,
5249      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5250     if (expected->ListIdentifier.cbData)
5251         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5252          expected->ListIdentifier.cbData),
5253          "%s: unexpected list identifier value\n", header);
5254     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5255      "%s: expected sequence number of %d bytes, got %d\n", header,
5256      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5257     if (expected->SequenceNumber.cbData)
5258         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5259          expected->SequenceNumber.cbData),
5260          "%s: unexpected sequence number value\n", header);
5261     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5262      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5263      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5264      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5265     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5266      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5267      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5268      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5269     if (expected->SubjectAlgorithm.pszObjId &&
5270      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5271         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5272          expected->SubjectAlgorithm.pszObjId);
5273     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5274         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5275          got->SubjectAlgorithm.pszObjId),
5276          "%s: expected subject algorithm %s, got %s\n", header,
5277          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5278     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5279      got->SubjectAlgorithm.Parameters.cbData,
5280      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5281      expected->SubjectAlgorithm.Parameters.cbData,
5282      got->SubjectAlgorithm.Parameters.cbData);
5283     if (expected->SubjectAlgorithm.Parameters.cbData)
5284         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5285          got->SubjectAlgorithm.Parameters.pbData,
5286          expected->SubjectAlgorithm.Parameters.cbData),
5287          "%s: unexpected subject algorithm parameter value\n", header);
5288     ok(expected->cCTLEntry == got->cCTLEntry,
5289      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5290      got->cCTLEntry);
5291     for (i = 0; i < expected->cCTLEntry; i++)
5292     {
5293         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5294          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5295          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5296          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5297          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5298         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5299             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5300              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5301              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5302              "%s[%d]: unexpected subject identifier value\n",
5303              header, i);
5304         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5305         {
5306             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5307              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5308              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5309              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5310              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5311             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5312             {
5313                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5314                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5315                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5316                  header, i, j, k,
5317                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5318                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5319                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5320                     ok(!memcmp(
5321                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5322                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5323                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5324                      "%s[%d][%d][%d]: unexpected value\n",
5325                      header, i, j, k);
5326             }
5327         }
5328     }
5329     ok(expected->cExtension == got->cExtension,
5330      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5331      got->cExtension);
5332     for (i = 0; i < expected->cExtension; i++)
5333     {
5334         ok(!strcmp(expected->rgExtension[i].pszObjId,
5335          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5336          header, i, expected->rgExtension[i].pszObjId,
5337          got->rgExtension[i].pszObjId);
5338         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5339          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5340          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5341         ok(expected->rgExtension[i].Value.cbData ==
5342          got->rgExtension[i].Value.cbData,
5343          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5344          header, i, expected->rgExtension[i].Value.cbData,
5345          got->rgExtension[i].Value.cbData);
5346         if (expected->rgExtension[i].Value.cbData)
5347             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5348              got->rgExtension[i].Value.pbData,
5349              expected->rgExtension[i].Value.cbData),
5350              "%s[%d]: unexpected extension value\n", header, i);
5351     }
5352 }
5353
5354 static const BYTE signedCTL[] = {
5355 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5356 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5357 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5358 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5359 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5360 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5361 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5362 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5363 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5364 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5365 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5366 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5367 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5368 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5369 static const BYTE signedCTLWithCTLInnerContent[] = {
5370 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5371 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5372 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5373 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5374 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5375 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5376 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5377 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5378 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5379 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5380 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5381 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5382 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5383 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5384 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5385 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5386 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5387 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5388 0x57,0x6c,0x0b,0x47,0xb8 };
5389
5390 static void test_decodeCTL(DWORD dwEncoding)
5391 {
5392     static char oid1[] = "1.2.3";
5393     static char oid2[] = "1.5.6";
5394     static BYTE nullData[] = { 5,0 };
5395     char *pOid1 = oid1;
5396     BOOL ret;
5397     BYTE *buf = NULL;
5398     DWORD size = 0;
5399     CTL_INFO info;
5400     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5401     CTL_ENTRY ctlEntry[2];
5402     CRYPT_ATTRIBUTE attr1, attr2;
5403     CRYPT_ATTR_BLOB value1, value2;
5404
5405     memset(&info, 0, sizeof(info));
5406     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5407      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5408     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5409     if (buf)
5410     {
5411         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5412         LocalFree(buf);
5413         buf = NULL;
5414     }
5415     info.dwVersion = 1;
5416     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5417      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5418      &size);
5419     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5420     if (buf)
5421     {
5422         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5423         LocalFree(buf);
5424         buf = NULL;
5425     }
5426     info.dwVersion = 0;
5427     info.SubjectUsage.cUsageIdentifier = 1;
5428     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5429     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5430      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5431      (BYTE *)&buf, &size);
5432     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5433     if (buf)
5434     {
5435         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5436         LocalFree(buf);
5437         buf = NULL;
5438     }
5439     info.SubjectUsage.cUsageIdentifier = 0;
5440     info.ListIdentifier.cbData = sizeof(serialNum);
5441     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5442     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5443      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5444      (BYTE *)&buf, &size);
5445     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5446     if (buf)
5447     {
5448         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5449         LocalFree(buf);
5450         buf = NULL;
5451     }
5452     info.ListIdentifier.cbData = 0;
5453     info.SequenceNumber.cbData = sizeof(serialNum);
5454     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5455     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5456      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5457      (BYTE *)&buf, &size);
5458     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5459     if (buf)
5460     {
5461         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5462         LocalFree(buf);
5463         buf = NULL;
5464     }
5465     info.SequenceNumber.cbData = 0;
5466     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5467     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5468      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5469      (BYTE *)&buf, &size);
5470     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5471     if (buf)
5472     {
5473         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5474         LocalFree(buf);
5475         buf = NULL;
5476     }
5477     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5478     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5479      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5480      (BYTE *)&buf, &size);
5481     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5482     if (buf)
5483     {
5484         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5485         LocalFree(buf);
5486         buf = NULL;
5487     }
5488     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5489     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5490     info.SubjectAlgorithm.pszObjId = oid2;
5491     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5492     info.SubjectAlgorithm.Parameters.pbData = nullData;
5493     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5494      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5495      (BYTE *)&buf, &size);
5496     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5497     if (buf)
5498     {
5499         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5500         LocalFree(buf);
5501         buf = NULL;
5502     }
5503     SetLastError(0xdeadbeef);
5504     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5505      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5506      (BYTE *)&buf, &size);
5507     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5508      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5509      GetLastError());
5510     info.SubjectAlgorithm.Parameters.cbData = 0;
5511     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5512     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5513     info.SubjectAlgorithm.pszObjId = oid2;
5514     info.SubjectAlgorithm.pszObjId = NULL;
5515     value1.cbData = sizeof(emptySequence);
5516     value1.pbData = (LPBYTE)emptySequence;
5517     attr1.pszObjId = oid1;
5518     attr1.cValue = 1;
5519     attr1.rgValue = &value1;
5520     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5521     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5522     ctlEntry[0].cAttribute = 1;
5523     ctlEntry[0].rgAttribute = &attr1;
5524     info.cCTLEntry = 1;
5525     info.rgCTLEntry = ctlEntry;
5526     SetLastError(0xdeadbeef);
5527     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5528      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5529      (BYTE *)&buf, &size);
5530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5531     if (buf)
5532     {
5533         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5534         LocalFree(buf);
5535         buf = NULL;
5536     }
5537     value2.cbData = sizeof(encodedIPAddr);
5538     value2.pbData = (LPBYTE)encodedIPAddr;
5539     attr2.pszObjId = oid2;
5540     attr2.cValue = 1;
5541     attr2.rgValue = &value2;
5542     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5543     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5544     ctlEntry[1].cAttribute = 1;
5545     ctlEntry[1].rgAttribute = &attr2;
5546     info.cCTLEntry = 2;
5547     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5548      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5549      (BYTE *)&buf, &size);
5550     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5551     if (buf)
5552     {
5553         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5554         LocalFree(buf);
5555         buf = NULL;
5556     }
5557     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5558     SetLastError(0xdeadbeef);
5559     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5560      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5561     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5562      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5563      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5564      GetLastError());
5565     SetLastError(0xdeadbeef);
5566     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5567      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5568      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5569     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5570      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5571      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5572      GetLastError());
5573 }
5574
5575 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5576 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5577  0x03,0,0,0,0,0,0 };
5578 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5579  0xa0,0x01,0x01 };
5580 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5581  0x03,0x02,0x01,0x01 };
5582 static BYTE bogusDER[] = { 1 };
5583
5584 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5585 {
5586     BOOL ret;
5587     BYTE *buf = NULL;
5588     DWORD size = 0;
5589     CRYPT_CONTENT_INFO info = { 0 };
5590     char oid1[] = "1.2.3";
5591
5592     if (0)
5593     {
5594         /* Crashes on win9x */
5595         SetLastError(0xdeadbeef);
5596         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5597          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5598         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5599          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5600     }
5601     SetLastError(0xdeadbeef);
5602     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5603      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5604     ok(!ret && (GetLastError() == E_INVALIDARG ||
5605      GetLastError() == OSS_LIMITED /* Win9x */),
5606      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5607     info.pszObjId = oid1;
5608     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5609      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5610     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5611     if (buf)
5612     {
5613         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5614         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5615         LocalFree(buf);
5616     }
5617     info.Content.pbData = bogusDER;
5618     info.Content.cbData = sizeof(bogusDER);
5619     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5620      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5621     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5622     if (buf)
5623     {
5624         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5625         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5626         LocalFree(buf);
5627     }
5628     info.Content.pbData = (BYTE *)ints[0].encoded;
5629     info.Content.cbData = ints[0].encoded[1] + 2;
5630     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5631      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5632     if (buf)
5633     {
5634         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5635         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5636         LocalFree(buf);
5637     }
5638 }
5639
5640 static const BYTE indefiniteSignedPKCSContent[] = {
5641 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5642 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5643 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5644 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5645 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5646 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5647 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5648 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5649 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5650 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5651 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5652 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5653 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5654 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5655 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5656 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5657 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5658 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5659 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5660 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5661 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5662 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5663 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5664 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5665 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5666 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5667 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5668 0x00,0x00,0x00,0x00,0x00,0x00 };
5669
5670 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5671 {
5672     BOOL ret;
5673     LPBYTE buf = NULL;
5674     DWORD size = 0;
5675     CRYPT_CONTENT_INFO *info;
5676
5677     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5678      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5679      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5680     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5681     if (buf)
5682     {
5683         info = (CRYPT_CONTENT_INFO *)buf;
5684
5685         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5686          info->pszObjId);
5687         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5688          info->Content.cbData);
5689         LocalFree(buf);
5690     }
5691     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5692      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5693      0, NULL, NULL, &size);
5694     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5695     SetLastError(0xdeadbeef);
5696     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5697      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5698      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5699     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5700      * I doubt an app depends on that.
5701      */
5702     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5703      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5704      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5705      GetLastError());
5706     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5707      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5708      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5709     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5710     if (buf)
5711     {
5712         info = (CRYPT_CONTENT_INFO *)buf;
5713
5714         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5715          info->pszObjId);
5716         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5717          "Unexpected size %d\n", info->Content.cbData);
5718         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5719          info->Content.cbData), "Unexpected value\n");
5720         LocalFree(buf);
5721     }
5722     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5723      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5724      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5725     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5726     if (buf)
5727     {
5728         info = (CRYPT_CONTENT_INFO *)buf;
5729
5730         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5731          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5732         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5733          info->Content.cbData);
5734         LocalFree(buf);
5735     }
5736 }
5737
5738 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5739  0x00 };
5740 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5741  0x01 };
5742 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5743  0x02,0x01,0x01 };
5744
5745 static void test_encodePKCSAttribute(DWORD dwEncoding)
5746 {
5747     CRYPT_ATTRIBUTE attr = { 0 };
5748     BOOL ret;
5749     LPBYTE buf = NULL;
5750     DWORD size = 0;
5751     CRYPT_ATTR_BLOB blob;
5752     char oid[] = "1.2.3";
5753
5754     if (0)
5755     {
5756         /* Crashes on win9x */
5757         SetLastError(0xdeadbeef);
5758         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5759          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5760         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5761          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5762     }
5763     SetLastError(0xdeadbeef);
5764     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5765      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5766     ok(!ret && (GetLastError() == E_INVALIDARG ||
5767      GetLastError() == OSS_LIMITED /* Win9x */),
5768      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5769     attr.pszObjId = oid;
5770     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5771      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5772     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5773     if (buf)
5774     {
5775         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5776         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5777         LocalFree(buf);
5778     }
5779     blob.cbData = sizeof(bogusDER);
5780     blob.pbData = bogusDER;
5781     attr.cValue = 1;
5782     attr.rgValue = &blob;
5783     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5784      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5785     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5786     if (buf)
5787     {
5788         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5789         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5790         LocalFree(buf);
5791     }
5792     blob.pbData = (BYTE *)ints[0].encoded;
5793     blob.cbData = ints[0].encoded[1] + 2;
5794     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5795      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5796     if (buf)
5797     {
5798         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5799         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5800         LocalFree(buf);
5801     }
5802 }
5803
5804 static void test_decodePKCSAttribute(DWORD dwEncoding)
5805 {
5806     BOOL ret;
5807     LPBYTE buf = NULL;
5808     DWORD size = 0;
5809     CRYPT_ATTRIBUTE *attr;
5810
5811     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5812      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5813      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5814     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5815     if (buf)
5816     {
5817         attr = (CRYPT_ATTRIBUTE *)buf;
5818
5819         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5820          attr->pszObjId);
5821         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5822         LocalFree(buf);
5823     }
5824     SetLastError(0xdeadbeef);
5825     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5826      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5827      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5828     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5829      * I doubt an app depends on that.
5830      */
5831     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5832      GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */),
5833      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5834      GetLastError());
5835     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5836      intPKCSAttr, sizeof(intPKCSAttr),
5837      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5838     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5839     if (buf)
5840     {
5841         attr = (CRYPT_ATTRIBUTE *)buf;
5842
5843         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5844          attr->pszObjId);
5845         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5846         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5847          "Unexpected size %d\n", attr->rgValue[0].cbData);
5848         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5849          attr->rgValue[0].cbData), "Unexpected value\n");
5850         LocalFree(buf);
5851     }
5852 }
5853
5854 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5855 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5856  0x2a,0x03,0x31,0x00 };
5857 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5858  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5859
5860 static void test_encodePKCSAttributes(DWORD dwEncoding)
5861 {
5862     CRYPT_ATTRIBUTES attributes = { 0 };
5863     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5864     CRYPT_ATTR_BLOB blob;
5865     BOOL ret;
5866     LPBYTE buf = NULL;
5867     DWORD size = 0;
5868     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5869
5870     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5871      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5872     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5873     if (buf)
5874     {
5875         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5876         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5877         LocalFree(buf);
5878     }
5879     attributes.cAttr = 1;
5880     attributes.rgAttr = attr;
5881     SetLastError(0xdeadbeef);
5882     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5883      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5884     ok(!ret && (GetLastError() == E_INVALIDARG ||
5885      GetLastError() == OSS_LIMITED /* Win9x */),
5886      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5887     attr[0].pszObjId = oid1;
5888     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5889      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5890     if (buf)
5891     {
5892         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5893         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5894         LocalFree(buf);
5895     }
5896     attr[1].pszObjId = oid2;
5897     attr[1].cValue = 1;
5898     attr[1].rgValue = &blob;
5899     blob.pbData = (BYTE *)ints[0].encoded;
5900     blob.cbData = ints[0].encoded[1] + 2;
5901     attributes.cAttr = 2;
5902     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5903      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5904     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5905     if (buf)
5906     {
5907         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5908         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5909         LocalFree(buf);
5910     }
5911 }
5912
5913 static void test_decodePKCSAttributes(DWORD dwEncoding)
5914 {
5915     BOOL ret;
5916     LPBYTE buf = NULL;
5917     DWORD size = 0;
5918     CRYPT_ATTRIBUTES *attributes;
5919
5920     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5921      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5922      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5923     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5924     if (buf)
5925     {
5926         attributes = (CRYPT_ATTRIBUTES *)buf;
5927         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5928          attributes->cAttr);
5929         LocalFree(buf);
5930     }
5931     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5932      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5933      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5934     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5935     if (buf)
5936     {
5937         attributes = (CRYPT_ATTRIBUTES *)buf;
5938         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5939          attributes->cAttr);
5940         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5941          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5942         ok(attributes->rgAttr[0].cValue == 0,
5943          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5944         LocalFree(buf);
5945     }
5946     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5947      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5948      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5949     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5950     if (buf)
5951     {
5952         attributes = (CRYPT_ATTRIBUTES *)buf;
5953         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5954          attributes->cAttr);
5955         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5956          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5957         ok(attributes->rgAttr[0].cValue == 0,
5958          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5959         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5960          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5961         ok(attributes->rgAttr[1].cValue == 1,
5962          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5963         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5964          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5965         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5966          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5967         LocalFree(buf);
5968     }
5969 }
5970
5971 static const BYTE singleCapability[] = {
5972 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5973 static const BYTE twoCapabilities[] = {
5974 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5975 static const BYTE singleCapabilitywithNULL[] = {
5976 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5977
5978 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5979 {
5980     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5981     BOOL ret;
5982     LPBYTE buf = NULL;
5983     DWORD size = 0;
5984     CRYPT_SMIME_CAPABILITY capability[2];
5985     CRYPT_SMIME_CAPABILITIES capabilities;
5986
5987     /* An empty capabilities is allowed */
5988     capabilities.cCapability = 0;
5989     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5990      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5991     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5992     if (buf)
5993     {
5994         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5995         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5996         LocalFree(buf);
5997     }
5998     /* A non-empty capabilities with an empty capability (lacking an OID) is
5999      * not allowed
6000      */
6001     capability[0].pszObjId = NULL;
6002     capability[0].Parameters.cbData = 0;
6003     capabilities.cCapability = 1;
6004     capabilities.rgCapability = capability;
6005     SetLastError(0xdeadbeef);
6006     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6007      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6008     ok(!ret && (GetLastError() == E_INVALIDARG ||
6009      GetLastError() == OSS_LIMITED /* Win9x */),
6010      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6011     capability[0].pszObjId = oid1;
6012     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6013      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6014     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6015     if (buf)
6016     {
6017         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6018         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6019         LocalFree(buf);
6020     }
6021     capability[1].pszObjId = oid2;
6022     capability[1].Parameters.cbData = 0;
6023     capabilities.cCapability = 2;
6024     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6025      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6026     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6027     if (buf)
6028     {
6029         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6030         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6031         LocalFree(buf);
6032     }
6033 }
6034
6035 static void compareSMimeCapabilities(LPCSTR header,
6036  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6037 {
6038     DWORD i;
6039
6040     ok(got->cCapability == expected->cCapability,
6041      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6042      got->cCapability);
6043     for (i = 0; i < expected->cCapability; i++)
6044     {
6045         ok(!strcmp(expected->rgCapability[i].pszObjId,
6046          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6047          header, i, expected->rgCapability[i].pszObjId,
6048          got->rgCapability[i].pszObjId);
6049         ok(expected->rgCapability[i].Parameters.cbData ==
6050          got->rgCapability[i].Parameters.cbData,
6051          "%s[%d]: expected %d bytes, got %d\n", header, i,
6052          expected->rgCapability[i].Parameters.cbData,
6053          got->rgCapability[i].Parameters.cbData);
6054         if (expected->rgCapability[i].Parameters.cbData)
6055             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6056              got->rgCapability[i].Parameters.pbData,
6057              expected->rgCapability[i].Parameters.cbData),
6058              "%s[%d]: unexpected value\n", header, i);
6059     }
6060 }
6061
6062 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6063 {
6064     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6065     BOOL ret;
6066     DWORD size = 0;
6067     CRYPT_SMIME_CAPABILITY capability[2];
6068     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6069
6070     SetLastError(0xdeadbeef);
6071     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6072      emptySequence, sizeof(emptySequence),
6073      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6074     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6075     if (ret)
6076     {
6077         capabilities.cCapability = 0;
6078         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6079         LocalFree(ptr);
6080     }
6081     SetLastError(0xdeadbeef);
6082     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6083      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6084      (BYTE *)&ptr, &size);
6085     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6086     if (ret)
6087     {
6088         capability[0].pszObjId = oid1;
6089         capability[0].Parameters.cbData = 0;
6090         capabilities.cCapability = 1;
6091         capabilities.rgCapability = capability;
6092         compareSMimeCapabilities("single capability", &capabilities, ptr);
6093         LocalFree(ptr);
6094     }
6095     SetLastError(0xdeadbeef);
6096     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6097      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6098      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6099     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6100     if (ret)
6101     {
6102         BYTE NULLparam[] = {0x05, 0x00};
6103         capability[0].pszObjId = oid1;
6104         capability[0].Parameters.cbData = 2;
6105         capability[0].Parameters.pbData = NULLparam;
6106         capabilities.cCapability = 1;
6107         capabilities.rgCapability = capability;
6108         compareSMimeCapabilities("single capability with NULL", &capabilities,
6109          ptr);
6110         LocalFree(ptr);
6111     }
6112     SetLastError(0xdeadbeef);
6113     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6114     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6115     (BYTE *)&ptr, &size);
6116     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6117     if (ret)
6118     {
6119         capability[0].Parameters.cbData = 0;
6120         capability[1].pszObjId = oid2;
6121         capability[1].Parameters.cbData = 0;
6122         capabilities.cCapability = 2;
6123         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6124         LocalFree(ptr);
6125     }
6126 }
6127
6128 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6129  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6130  0x67 };
6131 static const BYTE minimalPKCSSigner[] = {
6132  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6133  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6134  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6135 static const BYTE PKCSSignerWithSerial[] = {
6136  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6137  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6138  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6139  0x00 };
6140 static const BYTE PKCSSignerWithHashAlgo[] = {
6141  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,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  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6144  0x00,0x04,0x00 };
6145 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6146  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6147  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6148  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6149  0x06,0x05,0x00,0x04,0x00 };
6150 static const BYTE PKCSSignerWithHash[] = {
6151  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6152  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6153  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6154  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6155  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6156 static const BYTE PKCSSignerWithAuthAttr[] = {
6157 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6158 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6159 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6160 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6161 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6162 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6163 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6164
6165 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6166 {
6167     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6168     BOOL ret;
6169     LPBYTE buf = NULL;
6170     DWORD size = 0;
6171     CMSG_SIGNER_INFO info = { 0 };
6172     char oid_common_name[] = szOID_COMMON_NAME;
6173     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6174      (LPBYTE)encodedCommonName };
6175     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6176
6177     SetLastError(0xdeadbeef);
6178     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6179      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6180     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6181     {
6182         skip("no PKCS7_SIGNER_INFO encode support\n");
6183         return;
6184     }
6185     ok(!ret && (GetLastError() == E_INVALIDARG ||
6186      GetLastError() == OSS_LIMITED /* Win9x */),
6187      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6188     /* To be encoded, a signer must have an issuer at least, and the encoding
6189      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6190      * see decoding tests.)
6191      */
6192     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6193     info.Issuer.pbData = encodedCommonNameNoNull;
6194     SetLastError(0xdeadbeef);
6195     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6196      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6197     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6198         ok(!ret && GetLastError() == E_INVALIDARG,
6199          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6200     else
6201     {
6202         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6203          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6204         if (buf)
6205         {
6206             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6207             if (size == sizeof(minimalPKCSSigner))
6208                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6209             else
6210                 ok(0, "Unexpected value\n");
6211             LocalFree(buf);
6212         }
6213     }
6214     info.SerialNumber.cbData = sizeof(serialNum);
6215     info.SerialNumber.pbData = (BYTE *)serialNum;
6216     SetLastError(0xdeadbeef);
6217     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6218      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6219     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6220         ok(!ret && GetLastError() == E_INVALIDARG,
6221          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6222     else
6223     {
6224         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6225          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6226         if (buf)
6227         {
6228             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6229              size);
6230             if (size == sizeof(PKCSSignerWithSerial))
6231                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6232                  "Unexpected value\n");
6233             else
6234                 ok(0, "Unexpected value\n");
6235             LocalFree(buf);
6236         }
6237     }
6238     info.HashAlgorithm.pszObjId = oid1;
6239     SetLastError(0xdeadbeef);
6240     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6241      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6242     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6243         ok(!ret && GetLastError() == E_INVALIDARG,
6244          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6245     else
6246     {
6247         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6248          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6249         if (buf)
6250         {
6251             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6252              size);
6253             if (size == sizeof(PKCSSignerWithHashAlgo))
6254                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6255                  "Unexpected value\n");
6256             else
6257                 ok(0, "Unexpected value\n");
6258             LocalFree(buf);
6259         }
6260     }
6261     info.HashEncryptionAlgorithm.pszObjId = oid2;
6262     SetLastError(0xdeadbeef);
6263     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6264      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6265     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6266         ok(!ret && GetLastError() == E_INVALIDARG,
6267          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6268     else
6269     {
6270         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6271         if (buf)
6272         {
6273             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6274              "Unexpected size %d\n", size);
6275             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6276                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6277                  "Unexpected value\n");
6278             else
6279                 ok(0, "Unexpected value\n");
6280             LocalFree(buf);
6281         }
6282     }
6283     info.EncryptedHash.cbData = sizeof(hash);
6284     info.EncryptedHash.pbData = (BYTE *)hash;
6285     SetLastError(0xdeadbeef);
6286     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6287      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6288     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6289         ok(!ret && GetLastError() == E_INVALIDARG,
6290          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6291     else
6292     {
6293         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6294         if (buf)
6295         {
6296             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6297              size);
6298             if (size == sizeof(PKCSSignerWithHash))
6299                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6300                  "Unexpected value\n");
6301             else
6302                 ok(0, "Unexpected value\n");
6303             LocalFree(buf);
6304         }
6305     }
6306     info.AuthAttrs.cAttr = 1;
6307     info.AuthAttrs.rgAttr = &attr;
6308     SetLastError(0xdeadbeef);
6309     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6310      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6311     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6312         ok(!ret && GetLastError() == E_INVALIDARG,
6313          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6314     else
6315     {
6316         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6317         if (buf)
6318         {
6319             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6320              size);
6321             if (size == sizeof(PKCSSignerWithAuthAttr))
6322                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6323                  "Unexpected value\n");
6324             else
6325                 ok(0, "Unexpected value\n");
6326             LocalFree(buf);
6327         }
6328     }
6329 }
6330
6331 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6332 {
6333     BOOL ret;
6334     LPBYTE buf = NULL;
6335     DWORD size = 0;
6336     CMSG_SIGNER_INFO *info;
6337
6338     /* A PKCS signer can't be decoded without a serial number. */
6339     SetLastError(0xdeadbeef);
6340     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6341      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6342      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6343     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6344      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6345      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6346      GetLastError());
6347     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6348      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6349      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6350     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6351      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6352     if (buf)
6353     {
6354         info = (CMSG_SIGNER_INFO *)buf;
6355         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6356          info->dwVersion);
6357         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6358          "Unexpected size %d\n", info->Issuer.cbData);
6359         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6360          info->Issuer.cbData), "Unexpected value\n");
6361         ok(info->SerialNumber.cbData == sizeof(serialNum),
6362          "Unexpected size %d\n", info->SerialNumber.cbData);
6363         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6364          "Unexpected value\n");
6365         LocalFree(buf);
6366     }
6367     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6368      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6369      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6370     if (buf)
6371     {
6372         info = (CMSG_SIGNER_INFO *)buf;
6373         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6374          info->dwVersion);
6375         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6376          "Unexpected size %d\n", info->Issuer.cbData);
6377         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6378          info->Issuer.cbData), "Unexpected value\n");
6379         ok(info->SerialNumber.cbData == sizeof(serialNum),
6380          "Unexpected size %d\n", info->SerialNumber.cbData);
6381         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6382          "Unexpected value\n");
6383         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6384          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6385         LocalFree(buf);
6386     }
6387     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6388      PKCSSignerWithHashAndEncryptionAlgo,
6389      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6390      NULL, (BYTE *)&buf, &size);
6391     if (buf)
6392     {
6393         info = (CMSG_SIGNER_INFO *)buf;
6394         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6395          info->dwVersion);
6396         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6397          "Unexpected size %d\n", info->Issuer.cbData);
6398         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6399          info->Issuer.cbData), "Unexpected value\n");
6400         ok(info->SerialNumber.cbData == sizeof(serialNum),
6401          "Unexpected size %d\n", info->SerialNumber.cbData);
6402         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6403          "Unexpected value\n");
6404         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6405          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6406         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6407          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6408         LocalFree(buf);
6409     }
6410     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6411      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6412      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6413     if (buf)
6414     {
6415         info = (CMSG_SIGNER_INFO *)buf;
6416         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6417          info->dwVersion);
6418         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6419          "Unexpected size %d\n", info->Issuer.cbData);
6420         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6421          info->Issuer.cbData), "Unexpected value\n");
6422         ok(info->SerialNumber.cbData == sizeof(serialNum),
6423          "Unexpected size %d\n", info->SerialNumber.cbData);
6424         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6425          "Unexpected value\n");
6426         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6427          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6428         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6429          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6430         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6431          info->EncryptedHash.cbData);
6432         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6433          "Unexpected value\n");
6434         LocalFree(buf);
6435     }
6436     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6437      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6438      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6439     if (buf)
6440     {
6441         info = (CMSG_SIGNER_INFO *)buf;
6442         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6443          info->AuthAttrs.cAttr);
6444         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6445          "Expected %s, got %s\n", szOID_COMMON_NAME,
6446          info->AuthAttrs.rgAttr[0].pszObjId);
6447         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6448          info->AuthAttrs.rgAttr[0].cValue);
6449         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6450          sizeof(encodedCommonName), "Unexpected size %d\n",
6451          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6452         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6453          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6454         LocalFree(buf);
6455     }
6456 }
6457
6458 static const BYTE CMSSignerWithKeyId[] = {
6459 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6460 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6461
6462 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6463 {
6464     BOOL ret;
6465     LPBYTE buf = NULL;
6466     DWORD size = 0;
6467     CMSG_CMS_SIGNER_INFO info = { 0 };
6468     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6469
6470     SetLastError(0xdeadbeef);
6471     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6472      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6473     ok(!ret, "Expected failure, got %d\n", ret);
6474     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6475     {
6476         skip("no CMS_SIGNER_INFO encode support\n");
6477         return;
6478     }
6479     ok(GetLastError() == E_INVALIDARG,
6480        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6481     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6482     SetLastError(0xdeadbeef);
6483     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6484      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6485     ok(!ret, "Expected failure, got %d\n", ret);
6486     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6487     {
6488         skip("no CMS_SIGNER_INFO encode support\n");
6489         return;
6490     }
6491     ok(GetLastError() == E_INVALIDARG,
6492        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6493     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6494      * be a key id or a issuer serial number with at least the issuer set, and
6495      * the encoding must include PKCS_7_ASN_ENCODING.
6496      * (That isn't enough to be decoded, see decoding tests.)
6497      */
6498     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6499      sizeof(encodedCommonNameNoNull);
6500     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6501     SetLastError(0xdeadbeef);
6502     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6503      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6504     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6505         ok(!ret && GetLastError() == E_INVALIDARG,
6506          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6507     else
6508     {
6509         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6510         if (buf)
6511         {
6512             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6513             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6514             LocalFree(buf);
6515         }
6516     }
6517     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6518     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6519     SetLastError(0xdeadbeef);
6520     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6521      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6522     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6523         ok(!ret && GetLastError() == E_INVALIDARG,
6524          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6525     else
6526     {
6527         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6528         if (buf)
6529         {
6530             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6531              size);
6532             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6533             LocalFree(buf);
6534         }
6535     }
6536     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6537     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6538     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6539     SetLastError(0xdeadbeef);
6540     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6541      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6542     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6543         ok(!ret && GetLastError() == E_INVALIDARG,
6544          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6545     else
6546     {
6547         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6548         if (buf)
6549         {
6550             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6551              size);
6552             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6553             LocalFree(buf);
6554         }
6555     }
6556     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6557      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6558      * (see RFC 3852, section 5.3.)
6559      */
6560     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6561     U(info.SignerId).HashId.cbData = sizeof(hash);
6562     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6563     SetLastError(0xdeadbeef);
6564     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6565      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6566     ok(!ret && GetLastError() == E_INVALIDARG,
6567      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6568     /* Now with a hash algo */
6569     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6570     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6571      sizeof(encodedCommonNameNoNull);
6572     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6573     info.HashAlgorithm.pszObjId = oid1;
6574     SetLastError(0xdeadbeef);
6575     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6576      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6577     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6578         ok(!ret && GetLastError() == E_INVALIDARG,
6579          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6580     else
6581     {
6582         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6583         if (buf)
6584         {
6585             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6586              size);
6587             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6588              "Unexpected value\n");
6589             LocalFree(buf);
6590         }
6591     }
6592     info.HashEncryptionAlgorithm.pszObjId = oid2;
6593     SetLastError(0xdeadbeef);
6594     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6595      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6596     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6597         ok(!ret && GetLastError() == E_INVALIDARG,
6598          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6599     else
6600     {
6601         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6602         if (buf)
6603         {
6604             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6605              "Unexpected size %d\n", size);
6606             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6607              "Unexpected value\n");
6608             LocalFree(buf);
6609         }
6610     }
6611     info.EncryptedHash.cbData = sizeof(hash);
6612     info.EncryptedHash.pbData = (BYTE *)hash;
6613     SetLastError(0xdeadbeef);
6614     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6615      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6616     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6617         ok(!ret && GetLastError() == E_INVALIDARG,
6618          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6619     else
6620     {
6621         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6622         if (buf)
6623         {
6624             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6625              size);
6626             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6627             LocalFree(buf);
6628         }
6629     }
6630 }
6631
6632 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6633 {
6634     BOOL ret;
6635     LPBYTE buf = NULL;
6636     DWORD size = 0;
6637     CMSG_CMS_SIGNER_INFO *info;
6638     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6639
6640     /* A CMS signer can't be decoded without a serial number. */
6641     SetLastError(0xdeadbeef);
6642     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6643      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6644      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6645     ok(!ret, "expected failure\n");
6646     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6647     {
6648         skip("no CMS_SIGNER_INFO decode support\n");
6649         return;
6650     }
6651     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6652      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6653     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6654      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6655      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6656     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6657     if (buf)
6658     {
6659         info = (CMSG_CMS_SIGNER_INFO *)buf;
6660         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6661          info->dwVersion);
6662         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6663          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6664          info->SignerId.dwIdChoice);
6665         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6666          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6667          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6668         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6669          encodedCommonNameNoNull,
6670          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6671          "Unexpected value\n");
6672         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6673          sizeof(serialNum), "Unexpected size %d\n",
6674          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6675         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6676          serialNum, sizeof(serialNum)), "Unexpected value\n");
6677         LocalFree(buf);
6678     }
6679     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6680      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6681      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6682     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6683     if (buf)
6684     {
6685         info = (CMSG_CMS_SIGNER_INFO *)buf;
6686         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6687          info->dwVersion);
6688         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6689          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6690          info->SignerId.dwIdChoice);
6691         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6692          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6693          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6694         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6695          encodedCommonNameNoNull,
6696          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6697          "Unexpected value\n");
6698         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6699          sizeof(serialNum), "Unexpected size %d\n",
6700          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6701         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6702          serialNum, sizeof(serialNum)), "Unexpected value\n");
6703         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6704          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6705         LocalFree(buf);
6706     }
6707     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6708      PKCSSignerWithHashAndEncryptionAlgo,
6709      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6710      NULL, (BYTE *)&buf, &size);
6711     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6712     if (buf)
6713     {
6714         info = (CMSG_CMS_SIGNER_INFO *)buf;
6715         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6716          info->dwVersion);
6717         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6718          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6719          info->SignerId.dwIdChoice);
6720         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6721          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6722          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6723         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6724          encodedCommonNameNoNull,
6725          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6726          "Unexpected value\n");
6727         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6728          sizeof(serialNum), "Unexpected size %d\n",
6729          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6730         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6731          serialNum, sizeof(serialNum)), "Unexpected value\n");
6732         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6733          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6734         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6735          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6736         LocalFree(buf);
6737     }
6738     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6739      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6740      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6741     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6742     if (buf)
6743     {
6744         info = (CMSG_CMS_SIGNER_INFO *)buf;
6745         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6746          info->dwVersion);
6747         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6748          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6749          info->SignerId.dwIdChoice);
6750         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6751          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6752          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6753         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6754          encodedCommonNameNoNull,
6755          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6756          "Unexpected value\n");
6757         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6758          sizeof(serialNum), "Unexpected size %d\n",
6759          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6760         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6761          serialNum, sizeof(serialNum)), "Unexpected value\n");
6762         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6763          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6764         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6765          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6766         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6767          info->EncryptedHash.cbData);
6768         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6769          "Unexpected value\n");
6770         LocalFree(buf);
6771     }
6772     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6773      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6774      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6775     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6776     if (buf)
6777     {
6778         info = (CMSG_CMS_SIGNER_INFO *)buf;
6779         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6780          info->dwVersion);
6781         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6782          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6783          info->SignerId.dwIdChoice);
6784         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6785          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6786         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6787          "Unexpected value\n");
6788         LocalFree(buf);
6789     }
6790 }
6791
6792 static BYTE emptyDNSPermittedConstraints[] = {
6793 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6794 static BYTE emptyDNSExcludedConstraints[] = {
6795 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6796 static BYTE DNSExcludedConstraints[] = {
6797 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6798 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6799 static BYTE permittedAndExcludedConstraints[] = {
6800 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6801 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6802 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6803 static BYTE permittedAndExcludedWithMinConstraints[] = {
6804 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6805 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6806 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6807 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6808 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6809 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6810 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6811
6812 static void test_encodeNameConstraints(DWORD dwEncoding)
6813 {
6814     BOOL ret;
6815     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6816     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6817     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6818     LPBYTE buf;
6819     DWORD size;
6820
6821     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6822      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6823     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6824     {
6825         skip("no X509_NAME_CONSTRAINTS encode support\n");
6826         return;
6827     }
6828     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6829     if (ret)
6830     {
6831         ok(size == sizeof(emptySequence), "Unexpected size\n");
6832         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6833         LocalFree(buf);
6834     }
6835     constraints.cPermittedSubtree = 1;
6836     constraints.rgPermittedSubtree = &permitted;
6837     SetLastError(0xdeadbeef);
6838     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6839      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6840     ok(!ret && GetLastError() == E_INVALIDARG,
6841      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6842     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6843     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6844      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6845     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6846     if (ret)
6847     {
6848         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6849         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6850          "Unexpected value\n");
6851         LocalFree(buf);
6852     }
6853     constraints.cPermittedSubtree = 0;
6854     constraints.cExcludedSubtree = 1;
6855     constraints.rgExcludedSubtree = &excluded;
6856     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6857     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6858      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6859     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6860     if (ret)
6861     {
6862         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6863         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6864          "Unexpected value\n");
6865         LocalFree(buf);
6866     }
6867     U(excluded.Base).pwszURL = (LPWSTR)url;
6868     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6869      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6870     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6871     if (ret)
6872     {
6873         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6874         ok(!memcmp(buf, DNSExcludedConstraints, size),
6875          "Unexpected value\n");
6876         LocalFree(buf);
6877     }
6878     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6879     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6880     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6881     constraints.cPermittedSubtree = 1;
6882     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6883      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6884     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6885     if (ret)
6886     {
6887         ok(size == sizeof(permittedAndExcludedConstraints),
6888          "Unexpected size\n");
6889         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6890          "Unexpected value\n");
6891         LocalFree(buf);
6892     }
6893     permitted.dwMinimum = 5;
6894     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6895      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6896     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6897     if (ret)
6898     {
6899         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6900          "Unexpected size\n");
6901         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6902          "Unexpected value\n");
6903         LocalFree(buf);
6904     }
6905     permitted.fMaximum = TRUE;
6906     permitted.dwMaximum = 3;
6907     SetLastError(0xdeadbeef);
6908     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6909      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6910     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6911     if (ret)
6912     {
6913         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6914          "Unexpected size\n");
6915         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6916          "Unexpected value\n");
6917         LocalFree(buf);
6918     }
6919 }
6920
6921 struct EncodedNameConstraints
6922 {
6923     CRYPT_DATA_BLOB            encoded;
6924     CERT_NAME_CONSTRAINTS_INFO constraints;
6925 };
6926
6927 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6928  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6929 static CERT_GENERAL_SUBTREE DNSSubtree = {
6930  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6931 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6932  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6933 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6934  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6935 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6936  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6937
6938 struct EncodedNameConstraints encodedNameConstraints[] = {
6939  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6940  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6941    { 1, &emptyDNSSubtree, 0, NULL } },
6942  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6943    { 0, NULL, 1, &emptyDNSSubtree } },
6944  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6945    { 0, NULL, 1, &DNSSubtree } },
6946  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6947    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6948  { { sizeof(permittedAndExcludedWithMinConstraints),
6949      permittedAndExcludedWithMinConstraints },
6950    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6951  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6952      permittedAndExcludedWithMinMaxConstraints },
6953    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6954 };
6955
6956 static void test_decodeNameConstraints(DWORD dwEncoding)
6957 {
6958     BOOL ret;
6959     DWORD i;
6960     CERT_NAME_CONSTRAINTS_INFO *constraints;
6961
6962     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6963     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6964     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6965     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6966     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6967     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6968     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6969     for (i = 0;
6970      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6971      i++)
6972     {
6973         DWORD size;
6974
6975         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6976          encodedNameConstraints[i].encoded.pbData,
6977          encodedNameConstraints[i].encoded.cbData,
6978          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6979         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6980         {
6981             skip("no X509_NAME_CONSTRAINTS decode support\n");
6982             return;
6983         }
6984         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6985         if (ret)
6986         {
6987             DWORD j;
6988
6989             if (constraints->cPermittedSubtree !=
6990              encodedNameConstraints[i].constraints.cPermittedSubtree)
6991                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
6992                  encodedNameConstraints[i].constraints.cPermittedSubtree,
6993                  constraints->cPermittedSubtree);
6994             if (constraints->cPermittedSubtree ==
6995              encodedNameConstraints[i].constraints.cPermittedSubtree)
6996             {
6997                 for (j = 0; j < constraints->cPermittedSubtree; j++)
6998                 {
6999                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7000                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7001                 }
7002             }
7003             if (constraints->cExcludedSubtree !=
7004              encodedNameConstraints[i].constraints.cExcludedSubtree)
7005                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7006                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7007                  constraints->cExcludedSubtree);
7008             if (constraints->cExcludedSubtree ==
7009              encodedNameConstraints[i].constraints.cExcludedSubtree)
7010             {
7011                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7012                 {
7013                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7014                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7015                 }
7016             }
7017             LocalFree(constraints);
7018         }
7019     }
7020 }
7021
7022 /* Free *pInfo with HeapFree */
7023 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7024 {
7025     BOOL ret;
7026     DWORD size = 0;
7027     HCRYPTKEY key;
7028
7029     /* This crashes
7030     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7031      */
7032     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7033     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7034      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7035     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7036      &size);
7037     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7038      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7039     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7040      NULL, &size);
7041     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7042      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7043     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7044      0, NULL, NULL, &size);
7045     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7046      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7047     /* Test with no key */
7048     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7049      0, NULL, NULL, &size);
7050     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7051      GetLastError());
7052     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7053     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7054     if (ret)
7055     {
7056         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7057          NULL, 0, NULL, NULL, &size);
7058         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7059         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7060         if (*pInfo)
7061         {
7062             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7063              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7064             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7065              GetLastError());
7066             if (ret)
7067             {
7068                 /* By default (we passed NULL as the OID) the OID is
7069                  * szOID_RSA_RSA.
7070                  */
7071                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7072                  "Expected %s, got %s\n", szOID_RSA_RSA,
7073                  (*pInfo)->Algorithm.pszObjId);
7074             }
7075         }
7076     }
7077     CryptDestroyKey(key);
7078 }
7079
7080 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7081  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7082  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7083  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7084  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7085  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7086  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7087  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7088  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7089  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7090  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7091  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7092  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7093  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7094  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7095  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7096  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7097  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7098  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7099  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7100  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7101  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7102  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7103  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7104  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7105
7106 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7107 {
7108     BOOL ret;
7109     HCRYPTKEY key;
7110     PCCERT_CONTEXT context;
7111     DWORD dwSize;
7112     ALG_ID ai;
7113
7114     /* These crash
7115     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7116     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7117     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7118     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7119      NULL);
7120      */
7121     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7122     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7123      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7124     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7125     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7126      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7127     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7128      &key);
7129     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7130      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7131
7132     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7133     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7134      &key);
7135     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7136
7137     dwSize = sizeof(ai);
7138     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7139     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7140     if(ret)
7141     {
7142       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7143       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7144     }
7145
7146     CryptDestroyKey(key);
7147
7148     /* Repeat with forced algorithm */
7149     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7150      &key);
7151     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7152
7153     dwSize = sizeof(ai);
7154     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7155     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7156     if(ret)
7157     {
7158       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7159       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7160     }
7161
7162     CryptDestroyKey(key);
7163
7164     /* Test importing a public key from a certificate context */
7165     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7166      sizeof(expiredCert));
7167     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7168      GetLastError());
7169     if (context)
7170     {
7171         ok(!strcmp(szOID_RSA_RSA,
7172          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7173          "Expected %s, got %s\n", szOID_RSA_RSA,
7174          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7175         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7176          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7177         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7178         CryptDestroyKey(key);
7179         CertFreeCertificateContext(context);
7180     }
7181 }
7182
7183 static const char cspName[] = "WineCryptTemp";
7184
7185 static void testPortPublicKeyInfo(void)
7186 {
7187     HCRYPTPROV csp;
7188     BOOL ret;
7189     PCERT_PUBLIC_KEY_INFO info = NULL;
7190
7191     /* Just in case a previous run failed, delete this thing */
7192     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7193      CRYPT_DELETEKEYSET);
7194     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7195      CRYPT_NEWKEYSET);
7196
7197     testExportPublicKey(csp, &info);
7198     testImportPublicKey(csp, info);
7199
7200     HeapFree(GetProcessHeap(), 0, info);
7201     CryptReleaseContext(csp, 0);
7202     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7203      CRYPT_DELETEKEYSET);
7204 }
7205
7206 START_TEST(encode)
7207 {
7208     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7209      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7210     HMODULE hCrypt32;
7211     DWORD i;
7212
7213     hCrypt32 = GetModuleHandleA("crypt32.dll");
7214     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7215     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7216     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7217     {
7218         skip("CryptDecodeObjectEx() is not available\n");
7219         return;
7220     }
7221
7222     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7223     {
7224         test_encodeInt(encodings[i]);
7225         test_decodeInt(encodings[i]);
7226         test_encodeEnumerated(encodings[i]);
7227         test_decodeEnumerated(encodings[i]);
7228         test_encodeFiletime(encodings[i]);
7229         test_decodeFiletime(encodings[i]);
7230         test_encodeName(encodings[i]);
7231         test_decodeName(encodings[i]);
7232         test_encodeUnicodeName(encodings[i]);
7233         test_decodeUnicodeName(encodings[i]);
7234         test_encodeNameValue(encodings[i]);
7235         test_decodeNameValue(encodings[i]);
7236         test_encodeUnicodeNameValue(encodings[i]);
7237         test_decodeUnicodeNameValue(encodings[i]);
7238         test_encodeAltName(encodings[i]);
7239         test_decodeAltName(encodings[i]);
7240         test_encodeOctets(encodings[i]);
7241         test_decodeOctets(encodings[i]);
7242         test_encodeBits(encodings[i]);
7243         test_decodeBits(encodings[i]);
7244         test_encodeBasicConstraints(encodings[i]);
7245         test_decodeBasicConstraints(encodings[i]);
7246         test_encodeRsaPublicKey(encodings[i]);
7247         test_decodeRsaPublicKey(encodings[i]);
7248         test_encodeSequenceOfAny(encodings[i]);
7249         test_decodeSequenceOfAny(encodings[i]);
7250         test_encodeExtensions(encodings[i]);
7251         test_decodeExtensions(encodings[i]);
7252         test_encodePublicKeyInfo(encodings[i]);
7253         test_decodePublicKeyInfo(encodings[i]);
7254         test_encodeCertToBeSigned(encodings[i]);
7255         test_decodeCertToBeSigned(encodings[i]);
7256         test_encodeCert(encodings[i]);
7257         test_decodeCert(encodings[i]);
7258         test_encodeCRLDistPoints(encodings[i]);
7259         test_decodeCRLDistPoints(encodings[i]);
7260         test_encodeCRLIssuingDistPoint(encodings[i]);
7261         test_decodeCRLIssuingDistPoint(encodings[i]);
7262         test_encodeCRLToBeSigned(encodings[i]);
7263         test_decodeCRLToBeSigned(encodings[i]);
7264         test_encodeEnhancedKeyUsage(encodings[i]);
7265         test_decodeEnhancedKeyUsage(encodings[i]);
7266         test_encodeAuthorityKeyId(encodings[i]);
7267         test_decodeAuthorityKeyId(encodings[i]);
7268         test_encodeAuthorityKeyId2(encodings[i]);
7269         test_decodeAuthorityKeyId2(encodings[i]);
7270         test_encodeAuthorityInfoAccess(encodings[i]);
7271         test_decodeAuthorityInfoAccess(encodings[i]);
7272         test_encodeCTL(encodings[i]);
7273         test_decodeCTL(encodings[i]);
7274         test_encodePKCSContentInfo(encodings[i]);
7275         test_decodePKCSContentInfo(encodings[i]);
7276         test_encodePKCSAttribute(encodings[i]);
7277         test_decodePKCSAttribute(encodings[i]);
7278         test_encodePKCSAttributes(encodings[i]);
7279         test_decodePKCSAttributes(encodings[i]);
7280         test_encodePKCSSMimeCapabilities(encodings[i]);
7281         test_decodePKCSSMimeCapabilities(encodings[i]);
7282         test_encodePKCSSignerInfo(encodings[i]);
7283         test_decodePKCSSignerInfo(encodings[i]);
7284         test_encodeCMSSignerInfo(encodings[i]);
7285         test_decodeCMSSignerInfo(encodings[i]);
7286         test_encodeNameConstraints(encodings[i]);
7287         test_decodeNameConstraints(encodings[i]);
7288     }
7289     testPortPublicKeyInfo();
7290 }