d3dx8: Add a few tests for MatrixStack.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (buf)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (buf)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (buf)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (buf)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (buf)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (buf)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              (BYTE *)&val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (buf)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665          GetLastError() == OSS_DATA_ERROR /* Win9x */),
666          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
667          GetLastError());
668     }
669 }
670
671 static const char commonName[] = "Juan Lang";
672 static const char surName[] = "Lang";
673
674 static const BYTE emptySequence[] = { 0x30, 0 };
675 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
676 static const BYTE twoRDNs[] = {
677     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
678     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
679     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
680 static const BYTE encodedTwoRDNs[] = {
681 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
682 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
683 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
684 0x6e,0x67,0x00,
685 };
686
687 static const BYTE us[] = { 0x55, 0x53 };
688 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
689  0x74, 0x61 };
690 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
691  0x6f, 0x6c, 0x69, 0x73 };
692 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
693  0x76, 0x65, 0x72, 0x73 };
694 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
695  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
696 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
697  0x73, 0x74 };
698 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
699  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
700
701 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
702 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
703
704 static CHAR oid_us[]            = "2.5.4.6",
705             oid_minnesota[]     = "2.5.4.8",
706             oid_minneapolis[]   = "2.5.4.7",
707             oid_codeweavers[]   = "2.5.4.10",
708             oid_wine[]          = "2.5.4.11",
709             oid_localhostAttr[] = "2.5.4.3",
710             oid_aric[]          = "1.2.840.113549.1.9.1";
711 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
712                                     { RDNA(minnesota) },
713                                     { RDNA(minneapolis) },
714                                     { RDNA(codeweavers) },
715                                     { RDNA(wine) },
716                                     { RDNA(localhostAttr) },
717                                     { RDNIA5(aric) } };
718 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
719                                            { RDNA(localhostAttr) },
720                                            { RDNA(minnesota) },
721                                            { RDNA(minneapolis) },
722                                            { RDNA(codeweavers) },
723                                            { RDNA(wine) },
724                                            { RDNIA5(aric) } };
725
726 #undef RDNIA5
727 #undef RDNA
728
729 static const BYTE encodedRDNAttrs[] = {
730 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
731 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
732 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
733 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
734 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
735 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
736 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
737 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
738 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
739 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
740 };
741
742 static void test_encodeName(DWORD dwEncoding)
743 {
744     CERT_RDN_ATTR attrs[2];
745     CERT_RDN rdn;
746     CERT_NAME_INFO info;
747     static CHAR oid_common_name[] = szOID_COMMON_NAME,
748                 oid_sur_name[]    = szOID_SUR_NAME;
749     BYTE *buf = NULL;
750     DWORD size = 0;
751     BOOL ret;
752
753     if (0)
754     {
755         /* Test with NULL pvStructInfo (crashes on win9x) */
756         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
757          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
758         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
759          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
760     }
761     /* Test with empty CERT_NAME_INFO */
762     info.cRDN = 0;
763     info.rgRDN = NULL;
764     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
765      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
766     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
767     if (buf)
768     {
769         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
770          "Got unexpected encoding for empty name\n");
771         LocalFree(buf);
772     }
773     if (0)
774     {
775         /* Test with bogus CERT_RDN (crashes on win9x) */
776         info.cRDN = 1;
777         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
778          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
779         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
780          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
781     }
782     /* Test with empty CERT_RDN */
783     rdn.cRDNAttr = 0;
784     rdn.rgRDNAttr = NULL;
785     info.cRDN = 1;
786     info.rgRDN = &rdn;
787     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
788      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
789     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
790     if (buf)
791     {
792         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
793          "Got unexpected encoding for empty RDN array\n");
794         LocalFree(buf);
795     }
796     if (0)
797     {
798         /* Test with bogus attr array (crashes on win9x) */
799         rdn.cRDNAttr = 1;
800         rdn.rgRDNAttr = NULL;
801         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
802          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
803         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
804          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
805     }
806     /* oddly, a bogus OID is accepted by Windows XP; not testing.
807     attrs[0].pszObjId = "bogus";
808     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
809     attrs[0].Value.cbData = sizeof(commonName);
810     attrs[0].Value.pbData = (BYTE *)commonName;
811     rdn.cRDNAttr = 1;
812     rdn.rgRDNAttr = attrs;
813     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
814      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
815     ok(!ret, "Expected failure, got success\n");
816      */
817     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
818      * the encoded attributes to be swapped.
819      */
820     attrs[0].pszObjId = oid_common_name;
821     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
822     attrs[0].Value.cbData = sizeof(commonName);
823     attrs[0].Value.pbData = (BYTE *)commonName;
824     attrs[1].pszObjId = oid_sur_name;
825     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
826     attrs[1].Value.cbData = sizeof(surName);
827     attrs[1].Value.pbData = (BYTE *)surName;
828     rdn.cRDNAttr = 2;
829     rdn.rgRDNAttr = attrs;
830     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
831      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
832     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
833     if (buf)
834     {
835         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
836          "Got unexpected encoding for two RDN array\n");
837         LocalFree(buf);
838     }
839     /* A name can be "encoded" with previously encoded RDN attrs. */
840     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
841     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
842     attrs[0].Value.cbData = sizeof(twoRDNs);
843     rdn.cRDNAttr = 1;
844     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
845      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
846     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
847     if (buf)
848     {
849         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
850         ok(!memcmp(buf, encodedTwoRDNs, size),
851          "Unexpected value for re-endoded two RDN array\n");
852         LocalFree(buf);
853     }
854     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
855     rdn.cRDNAttr = 1;
856     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
857     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
858      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
859     ok(!ret && GetLastError() == E_INVALIDARG,
860      "Expected E_INVALIDARG, got %08x\n", GetLastError());
861     /* Test a more complex name */
862     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
863     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
864     info.cRDN = 1;
865     info.rgRDN = &rdn;
866     buf = NULL;
867     size = 0;
868     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
869      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
870     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
871     if (ret)
872     {
873         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
874         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
875         LocalFree(buf);
876     }
877 }
878
879 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
880 static WCHAR surNameW[] = { 'L','a','n','g',0 };
881
882 static const BYTE twoRDNsNoNull[] = {
883  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
884  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
885  0x20,0x4c,0x61,0x6e,0x67 };
886 static const BYTE anyType[] = {
887  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
888  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
889  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
890  0x61,0x4c,0x67,0x6e };
891
892 static void test_encodeUnicodeName(DWORD dwEncoding)
893 {
894     CERT_RDN_ATTR attrs[2];
895     CERT_RDN rdn;
896     CERT_NAME_INFO info;
897     static CHAR oid_common_name[] = szOID_COMMON_NAME,
898                 oid_sur_name[]    = szOID_SUR_NAME;
899     BYTE *buf = NULL;
900     DWORD size = 0;
901     BOOL ret;
902
903     if (0)
904     {
905         /* Test with NULL pvStructInfo (crashes on win9x) */
906         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
907          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
908         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
909          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
910     }
911     /* Test with empty CERT_NAME_INFO */
912     info.cRDN = 0;
913     info.rgRDN = NULL;
914     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
915      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
916     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
917     if (buf)
918     {
919         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
920          "Got unexpected encoding for empty name\n");
921         LocalFree(buf);
922     }
923     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
924      * encoding (the NULL).
925      */
926     attrs[0].pszObjId = oid_common_name;
927     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
928     attrs[0].Value.cbData = sizeof(commonNameW);
929     attrs[0].Value.pbData = (BYTE *)commonNameW;
930     rdn.cRDNAttr = 1;
931     rdn.rgRDNAttr = attrs;
932     info.cRDN = 1;
933     info.rgRDN = &rdn;
934     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
935      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
936     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
937      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
938     ok(size == 9, "Unexpected error index %08x\n", size);
939     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
940      * forces the order of the encoded attributes to be swapped.
941      */
942     attrs[0].pszObjId = oid_common_name;
943     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
944     attrs[0].Value.cbData = 0;
945     attrs[0].Value.pbData = (BYTE *)commonNameW;
946     attrs[1].pszObjId = oid_sur_name;
947     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
948     attrs[1].Value.cbData = 0;
949     attrs[1].Value.pbData = (BYTE *)surNameW;
950     rdn.cRDNAttr = 2;
951     rdn.rgRDNAttr = attrs;
952     info.cRDN = 1;
953     info.rgRDN = &rdn;
954     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
955      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
956     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
957     if (buf)
958     {
959         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
960          "Got unexpected encoding for two RDN array\n");
961         LocalFree(buf);
962     }
963     /* A name can be "encoded" with previously encoded RDN attrs. */
964     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
965     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
966     attrs[0].Value.cbData = sizeof(twoRDNs);
967     rdn.cRDNAttr = 1;
968     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
969      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
970     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
971     if (buf)
972     {
973         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
974         ok(!memcmp(buf, encodedTwoRDNs, size),
975          "Unexpected value for re-endoded two RDN array\n");
976         LocalFree(buf);
977     }
978     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
979     rdn.cRDNAttr = 1;
980     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
981     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
982      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
983     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
984     if (buf)
985     {
986         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
987         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
988         LocalFree(buf);
989     }
990 }
991
992 static void compareNameValues(const CERT_NAME_VALUE *expected,
993  const CERT_NAME_VALUE *got)
994 {
995     ok(got->dwValueType == expected->dwValueType,
996      "Expected string type %d, got %d\n", expected->dwValueType,
997      got->dwValueType);
998     ok(got->Value.cbData == expected->Value.cbData,
999      "String type %d: unexpected data size, got %d, expected %d\n",
1000      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1001     if (got->Value.cbData && got->Value.pbData)
1002         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1003          min(got->Value.cbData, expected->Value.cbData)),
1004          "String type %d: unexpected value\n", expected->dwValueType);
1005 }
1006
1007 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1008  const CERT_RDN_ATTR *got)
1009 {
1010     if (expected->pszObjId && strlen(expected->pszObjId))
1011     {
1012         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1013          expected->pszObjId);
1014         if (got->pszObjId)
1015         {
1016             ok(!strcmp(got->pszObjId, expected->pszObjId),
1017              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1018              expected->pszObjId);
1019         }
1020     }
1021     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1022      (const CERT_NAME_VALUE *)&got->dwValueType);
1023 }
1024
1025 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1026 {
1027     ok(got->cRDNAttr == expected->cRDNAttr,
1028      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1029     if (got->cRDNAttr)
1030     {
1031         DWORD i;
1032
1033         for (i = 0; i < got->cRDNAttr; i++)
1034             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1035     }
1036 }
1037
1038 static void compareNames(const CERT_NAME_INFO *expected,
1039  const CERT_NAME_INFO *got)
1040 {
1041     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1042      expected->cRDN, got->cRDN);
1043     if (got->cRDN)
1044     {
1045         DWORD i;
1046
1047         for (i = 0; i < got->cRDN; i++)
1048             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1049     }
1050 }
1051
1052 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1053 static const BYTE twoRDNsExtraBytes[] = {
1054     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1055     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1056     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1057
1058 static void test_decodeName(DWORD dwEncoding)
1059 {
1060     BYTE *buf = NULL;
1061     DWORD bufSize = 0;
1062     BOOL ret;
1063     CERT_RDN rdn;
1064     CERT_NAME_INFO info = { 1, &rdn };
1065
1066     /* test empty name */
1067     bufSize = 0;
1068     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1069      emptySequence[1] + 2,
1070      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1071      (BYTE *)&buf, &bufSize);
1072     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1073     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1074      * decoder works the same way, so only test the count.
1075      */
1076     if (buf)
1077     {
1078         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1079         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1080          "Expected 0 RDNs in empty info, got %d\n",
1081          ((CERT_NAME_INFO *)buf)->cRDN);
1082         LocalFree(buf);
1083     }
1084     /* test empty name with indefinite-length encoding */
1085     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1086      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1087      (BYTE *)&buf, &bufSize);
1088     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1089     if (ret)
1090     {
1091         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1092         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1093          "Expected 0 RDNs in empty info, got %d\n",
1094          ((CERT_NAME_INFO *)buf)->cRDN);
1095         LocalFree(buf);
1096     }
1097     /* test empty RDN */
1098     bufSize = 0;
1099     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1100      emptyRDNs[1] + 2,
1101      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1102      (BYTE *)&buf, &bufSize);
1103     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1104     if (buf)
1105     {
1106         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1107
1108         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1109          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1110          "Got unexpected value for empty RDN\n");
1111         LocalFree(buf);
1112     }
1113     /* test two RDN attrs */
1114     bufSize = 0;
1115     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1116      twoRDNs[1] + 2,
1117      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1118      (BYTE *)&buf, &bufSize);
1119     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1120     if (buf)
1121     {
1122         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1123                     oid_common_name[] = szOID_COMMON_NAME;
1124
1125         CERT_RDN_ATTR attrs[] = {
1126          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1127           (BYTE *)surName } },
1128          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1129           (BYTE *)commonName } },
1130         };
1131
1132         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1133         rdn.rgRDNAttr = attrs;
1134         compareNames(&info, (CERT_NAME_INFO *)buf);
1135         LocalFree(buf);
1136     }
1137     /* test that two RDN attrs with extra bytes succeeds */
1138     bufSize = 0;
1139     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1140      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1141     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1142     /* And, a slightly more complicated name */
1143     buf = NULL;
1144     bufSize = 0;
1145     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1146      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1147     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1148     if (ret)
1149     {
1150         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1151         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1152         compareNames(&info, (CERT_NAME_INFO *)buf);
1153         LocalFree(buf);
1154     }
1155 }
1156
1157 static void test_decodeUnicodeName(DWORD dwEncoding)
1158 {
1159     BYTE *buf = NULL;
1160     DWORD bufSize = 0;
1161     BOOL ret;
1162     CERT_RDN rdn;
1163     CERT_NAME_INFO info = { 1, &rdn };
1164
1165     /* test empty name */
1166     bufSize = 0;
1167     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1168      emptySequence[1] + 2,
1169      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1170      (BYTE *)&buf, &bufSize);
1171     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1172     if (buf)
1173     {
1174         ok(bufSize == sizeof(CERT_NAME_INFO),
1175          "Got wrong bufSize %d\n", bufSize);
1176         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1177          "Expected 0 RDNs in empty info, got %d\n",
1178          ((CERT_NAME_INFO *)buf)->cRDN);
1179         LocalFree(buf);
1180     }
1181     /* test empty RDN */
1182     bufSize = 0;
1183     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1184      emptyRDNs[1] + 2,
1185      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1186      (BYTE *)&buf, &bufSize);
1187     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1188     if (buf)
1189     {
1190         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1191
1192         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1193          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1194          "Got unexpected value for empty RDN\n");
1195         LocalFree(buf);
1196     }
1197     /* test two RDN attrs */
1198     bufSize = 0;
1199     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1200      sizeof(twoRDNsNoNull),
1201      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1202      (BYTE *)&buf, &bufSize);
1203     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1204     if (buf)
1205     {
1206         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1207                     oid_common_name[] = szOID_COMMON_NAME;
1208
1209         CERT_RDN_ATTR attrs[] = {
1210          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1211          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1212          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1213          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1214         };
1215
1216         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1217         rdn.rgRDNAttr = attrs;
1218         compareNames(&info, (CERT_NAME_INFO *)buf);
1219         LocalFree(buf);
1220     }
1221 }
1222
1223 struct EncodedNameValue
1224 {
1225     CERT_NAME_VALUE value;
1226     const BYTE *encoded;
1227     DWORD encodedSize;
1228 };
1229
1230 static const char bogusIA5[] = "\x80";
1231 static const char bogusPrintable[] = "~";
1232 static const char bogusNumeric[] = "A";
1233 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1234 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1235 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1236 static BYTE octetCommonNameValue[] = {
1237  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1238 static BYTE numericCommonNameValue[] = {
1239  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1240 static BYTE printableCommonNameValue[] = {
1241  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1242 static BYTE t61CommonNameValue[] = {
1243  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1244 static BYTE videotexCommonNameValue[] = {
1245  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE ia5CommonNameValue[] = {
1247  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE graphicCommonNameValue[] = {
1249  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE visibleCommonNameValue[] = {
1251  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE generalCommonNameValue[] = {
1253  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE bmpCommonNameValue[] = {
1255  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1256  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1257 static BYTE utf8CommonNameValue[] = {
1258  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1259
1260 static struct EncodedNameValue nameValues[] = {
1261  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1262      octetCommonNameValue, sizeof(octetCommonNameValue) },
1263  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1264      numericCommonNameValue, sizeof(numericCommonNameValue) },
1265  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1266      printableCommonNameValue, sizeof(printableCommonNameValue) },
1267  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1268      t61CommonNameValue, sizeof(t61CommonNameValue) },
1269  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1271  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1273  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1275  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1277  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278      generalCommonNameValue, sizeof(generalCommonNameValue) },
1279  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1280      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1281  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1282      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1283  /* The following tests succeed under Windows, but really should fail,
1284   * they contain characters that are illegal for the encoding.  I'm
1285   * including them to justify my lazy encoding.
1286   */
1287  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1288      sizeof(bin42) },
1289  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1290      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1291  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1292      bin44, sizeof(bin44) },
1293 };
1294
1295 static void test_encodeNameValue(DWORD dwEncoding)
1296 {
1297     BYTE *buf = NULL;
1298     DWORD size = 0, i;
1299     BOOL ret;
1300     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1301
1302     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1303     value.Value.pbData = printableCommonNameValue;
1304     value.Value.cbData = sizeof(printableCommonNameValue);
1305     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1306      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1307     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1308     if (buf)
1309     {
1310         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1311          size);
1312         ok(!memcmp(buf, printableCommonNameValue, size),
1313          "Unexpected encoding\n");
1314         LocalFree(buf);
1315     }
1316     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1317     {
1318         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1319          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1320          &size);
1321         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1322          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1323          nameValues[i].value.dwValueType, GetLastError());
1324         if (ret)
1325         {
1326             ok(size == nameValues[i].encodedSize,
1327              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1328             ok(!memcmp(buf, nameValues[i].encoded, size),
1329              "Got unexpected encoding\n");
1330             LocalFree(buf);
1331         }
1332     }
1333 }
1334
1335 static void test_decodeNameValue(DWORD dwEncoding)
1336 {
1337     int i;
1338     BYTE *buf = NULL;
1339     DWORD bufSize = 0;
1340     BOOL ret;
1341
1342     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1343     {
1344         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1345          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1346          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1347          (BYTE *)&buf, &bufSize);
1348         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1349          nameValues[i].value.dwValueType, GetLastError());
1350         if (ret)
1351         {
1352             compareNameValues(&nameValues[i].value,
1353              (const CERT_NAME_VALUE *)buf);
1354             LocalFree(buf);
1355         }
1356     }
1357 }
1358
1359 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1360 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1361 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1362  'h','q','.','o','r','g',0 };
1363 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1364  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1365  0x6f, 0x72, 0x67 };
1366 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1367  0x575b, 0 };
1368 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1369 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1370  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1371 static const BYTE localhost[] = { 127, 0, 0, 1 };
1372 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1373  0x01 };
1374 static const unsigned char encodedCommonName[] = {
1375     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1376 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1377 static const BYTE encodedDirectoryName[] = {
1378 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1379 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1380
1381 static void test_encodeAltName(DWORD dwEncoding)
1382 {
1383     CERT_ALT_NAME_INFO info = { 0 };
1384     CERT_ALT_NAME_ENTRY entry = { 0 };
1385     BYTE *buf = NULL;
1386     DWORD size = 0;
1387     BOOL ret;
1388     char oid[] = "1.2.3";
1389
1390     /* Test with empty info */
1391     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1392      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1393     if (buf)
1394     {
1395         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1396         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1397         LocalFree(buf);
1398     }
1399     /* Test with an empty entry */
1400     info.cAltEntry = 1;
1401     info.rgAltEntry = &entry;
1402     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1403      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1404     ok(!ret && GetLastError() == E_INVALIDARG,
1405      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1406     /* Test with an empty pointer */
1407     entry.dwAltNameChoice = CERT_ALT_NAME_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(emptyURL), "Wrong size %d\n", size);
1413         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1414         LocalFree(buf);
1415     }
1416     /* Test with a real URL */
1417     U(entry).pwszURL = (LPWSTR)url;
1418     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1419      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1420     if (buf)
1421     {
1422         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1423         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1424         LocalFree(buf);
1425     }
1426     /* Now with the URL containing an invalid IA5 char */
1427     U(entry).pwszURL = (LPWSTR)nihongoURL;
1428     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1429      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1430     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1431      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1432     /* The first invalid character is at index 7 */
1433     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1434      "Expected invalid char at index 7, got %d\n",
1435      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1436     /* Now with the URL missing a scheme */
1437     U(entry).pwszURL = (LPWSTR)dnsName;
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         /* This succeeds, but it shouldn't, so don't worry about conforming */
1444         LocalFree(buf);
1445     }
1446     /* Now with a DNS name */
1447     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1448     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1449      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1450     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1451     if (buf)
1452     {
1453         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1454         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1455         LocalFree(buf);
1456     }
1457     /* Test with an IP address */
1458     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1459     U(entry).IPAddress.cbData = sizeof(localhost);
1460     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1461     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1462      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1463     if (buf)
1464     {
1465         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1466         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1467         LocalFree(buf);
1468     }
1469     /* Test with OID */
1470     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1471     U(entry).pszRegisteredID = oid;
1472     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1473      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1474     if (buf)
1475     {
1476         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1477         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1478         LocalFree(buf);
1479     }
1480     /* Test with directory name */
1481     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1482     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1483     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1484     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1485      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1486     if (buf)
1487     {
1488         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1489         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1490         LocalFree(buf);
1491     }
1492 }
1493
1494 static void test_decodeAltName(DWORD dwEncoding)
1495 {
1496     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1497      0x00, 0x00, 0x01 };
1498     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1499      0x01 };
1500     BOOL ret;
1501     BYTE *buf = NULL;
1502     DWORD bufSize = 0;
1503     CERT_ALT_NAME_INFO *info;
1504
1505     /* Test some bogus ones first */
1506     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1507      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1508      NULL, (BYTE *)&buf, &bufSize);
1509     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1510      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1511      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1512      GetLastError());
1513     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1514      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1515      &bufSize);
1516     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1517      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1518      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1519      GetLastError());
1520     /* Now expected cases */
1521     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1522      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1523      &bufSize);
1524     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1525     if (buf)
1526     {
1527         info = (CERT_ALT_NAME_INFO *)buf;
1528
1529         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1530          info->cAltEntry);
1531         LocalFree(buf);
1532     }
1533     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1534      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1535      &bufSize);
1536     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1537     if (buf)
1538     {
1539         info = (CERT_ALT_NAME_INFO *)buf;
1540
1541         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1542          info->cAltEntry);
1543         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1544          "Expected CERT_ALT_NAME_URL, got %d\n",
1545          info->rgAltEntry[0].dwAltNameChoice);
1546         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1547          "Expected empty URL\n");
1548         LocalFree(buf);
1549     }
1550     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1551      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1552     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1553     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1554      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1555      &bufSize);
1556     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1557     if (buf)
1558     {
1559         info = (CERT_ALT_NAME_INFO *)buf;
1560
1561         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1562          info->cAltEntry);
1563         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1564          "Expected CERT_ALT_NAME_URL, got %d\n",
1565          info->rgAltEntry[0].dwAltNameChoice);
1566         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1567         LocalFree(buf);
1568     }
1569     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1570      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1571      &bufSize);
1572     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1573     if (buf)
1574     {
1575         info = (CERT_ALT_NAME_INFO *)buf;
1576
1577         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1578          info->cAltEntry);
1579         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1580          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1581          info->rgAltEntry[0].dwAltNameChoice);
1582         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1583          "Unexpected DNS name\n");
1584         LocalFree(buf);
1585     }
1586     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1587      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1588      &bufSize);
1589     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1590     if (buf)
1591     {
1592         info = (CERT_ALT_NAME_INFO *)buf;
1593
1594         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1595          info->cAltEntry);
1596         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1597          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1598          info->rgAltEntry[0].dwAltNameChoice);
1599         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1600          "Unexpected IP address length %d\n",
1601           U(info->rgAltEntry[0]).IPAddress.cbData);
1602         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1603          sizeof(localhost)), "Unexpected IP address value\n");
1604         LocalFree(buf);
1605     }
1606     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1607      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1608      &bufSize);
1609     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1610     if (buf)
1611     {
1612         info = (CERT_ALT_NAME_INFO *)buf;
1613
1614         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1615          info->cAltEntry);
1616         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1617          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1618          info->rgAltEntry[0].dwAltNameChoice);
1619         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1620            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1621         LocalFree(buf);
1622     }
1623     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1624      encodedDirectoryName, sizeof(encodedDirectoryName),
1625      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1626     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1627     if (buf)
1628     {
1629         info = (CERT_ALT_NAME_INFO *)buf;
1630
1631         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1632          info->cAltEntry);
1633         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1634          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1635          info->rgAltEntry[0].dwAltNameChoice);
1636         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1637          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1638           U(info->rgAltEntry[0]).DirectoryName.cbData);
1639         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1640          encodedCommonName, sizeof(encodedCommonName)),
1641          "Unexpected directory name value\n");
1642         LocalFree(buf);
1643     }
1644 }
1645
1646 struct UnicodeExpectedError
1647 {
1648     DWORD   valueType;
1649     LPCWSTR str;
1650     DWORD   errorIndex;
1651     DWORD   error;
1652 };
1653
1654 static const WCHAR oneW[] = { '1',0 };
1655 static const WCHAR aW[] = { 'a',0 };
1656 static const WCHAR quoteW[] = { '"', 0 };
1657
1658 static struct UnicodeExpectedError unicodeErrors[] = {
1659  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1660  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1661  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1662  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1663  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1664  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1665 };
1666
1667 struct UnicodeExpectedResult
1668 {
1669     DWORD           valueType;
1670     LPCWSTR         str;
1671     CRYPT_DATA_BLOB encoded;
1672 };
1673
1674 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1675 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1676 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1677 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1678 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1679 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1680 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1681 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1682 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1683 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1684 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1685 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1686  0x5b };
1687 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1688  0x6f,0x5b };
1689 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1690  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1691 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1692  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1693
1694 static struct UnicodeExpectedResult unicodeResults[] = {
1695  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1696  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1697  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1698  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1699  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1700  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1701  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1702  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1703  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1704  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1705  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1706  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1707  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1708 };
1709
1710 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1711  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1712  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1713 };
1714
1715 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1716 {
1717     BYTE *buf = NULL;
1718     DWORD size = 0, i;
1719     BOOL ret;
1720     CERT_NAME_VALUE value;
1721
1722     if (0)
1723     {
1724         /* Crashes on win9x */
1725         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1726          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1727         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1728          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1729     }
1730     /* Have to have a string of some sort */
1731     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1732     value.Value.pbData = NULL;
1733     value.Value.cbData = 0;
1734     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1735      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1736     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1737      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1738     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1739     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1740      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1741     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1742      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1743     value.dwValueType = CERT_RDN_ANY_TYPE;
1744     value.Value.pbData = (LPBYTE)oneW;
1745     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1746      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1747     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1748      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1749     value.Value.cbData = sizeof(oneW);
1750     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1751      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1752     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1753      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1754     /* An encoded string with specified length isn't good enough either */
1755     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1756     value.Value.pbData = oneUniversal;
1757     value.Value.cbData = sizeof(oneUniversal);
1758     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1759      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1760     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1761      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1762     /* More failure checking */
1763     value.Value.cbData = 0;
1764     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1765     {
1766         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1767         value.dwValueType = unicodeErrors[i].valueType;
1768         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1769          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1770         ok(!ret && GetLastError() == unicodeErrors[i].error,
1771          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1772          unicodeErrors[i].error, GetLastError());
1773         ok(size == unicodeErrors[i].errorIndex,
1774          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1775          size);
1776     }
1777     /* cbData can be zero if the string is NULL-terminated */
1778     value.Value.cbData = 0;
1779     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1780     {
1781         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1782         value.dwValueType = unicodeResults[i].valueType;
1783         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1784          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1785         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1786          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1787         if (buf)
1788         {
1789             ok(size == unicodeResults[i].encoded.cbData,
1790              "Value type %d: expected size %d, got %d\n",
1791              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1792             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1793              "Value type %d: unexpected value\n", value.dwValueType);
1794             LocalFree(buf);
1795         }
1796     }
1797     /* These "encode," but they do so by truncating each unicode character
1798      * rather than properly encoding it.  Kept separate from the proper results,
1799      * because the encoded forms won't decode to their original strings.
1800      */
1801     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1802     {
1803         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1804         value.dwValueType = unicodeWeirdness[i].valueType;
1805         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1806          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1807         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1808         if (buf)
1809         {
1810             ok(size == unicodeWeirdness[i].encoded.cbData,
1811              "Value type %d: expected size %d, got %d\n",
1812              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1813             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1814              "Value type %d: unexpected value\n", value.dwValueType);
1815             LocalFree(buf);
1816         }
1817     }
1818 }
1819
1820 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1821 {
1822     if (n <= 0) return 0;
1823     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1824     return *str1 - *str2;
1825 }
1826
1827 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1828 {
1829     DWORD i;
1830
1831     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1832     {
1833         BYTE *buf = NULL;
1834         BOOL ret;
1835         DWORD size = 0;
1836
1837         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1838          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1839          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1840         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1841          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1842         if (ret && buf)
1843         {
1844             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1845
1846             ok(value->dwValueType == unicodeResults[i].valueType,
1847              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1848              value->dwValueType);
1849             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1850              value->Value.cbData / sizeof(WCHAR)),
1851              "Unexpected decoded value for index %d (value type %d)\n", i,
1852              unicodeResults[i].valueType);
1853             LocalFree(buf);
1854         }
1855     }
1856 }
1857
1858 struct encodedOctets
1859 {
1860     const BYTE *val;
1861     const BYTE *encoded;
1862 };
1863
1864 static const unsigned char bin46[] = { 'h','i',0 };
1865 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1866 static const unsigned char bin48[] = {
1867      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1868 static const unsigned char bin49[] = {
1869      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1870 static const unsigned char bin50[] = { 0 };
1871 static const unsigned char bin51[] = { 0x04,0x00,0 };
1872
1873 static const struct encodedOctets octets[] = {
1874     { bin46, bin47 },
1875     { bin48, bin49 },
1876     { bin50, bin51 },
1877 };
1878
1879 static void test_encodeOctets(DWORD dwEncoding)
1880 {
1881     CRYPT_DATA_BLOB blob;
1882     DWORD i;
1883
1884     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1885     {
1886         BYTE *buf = NULL;
1887         BOOL ret;
1888         DWORD bufSize = 0;
1889
1890         blob.cbData = strlen((const char*)octets[i].val);
1891         blob.pbData = (BYTE*)octets[i].val;
1892         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1893          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1894         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1895         if (buf)
1896         {
1897             ok(buf[0] == 4,
1898              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1899             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1900              buf[1], octets[i].encoded[1]);
1901             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1902              octets[i].encoded[1] + 1), "Got unexpected value\n");
1903             LocalFree(buf);
1904         }
1905     }
1906 }
1907
1908 static void test_decodeOctets(DWORD dwEncoding)
1909 {
1910     DWORD i;
1911
1912     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1913     {
1914         BYTE *buf = NULL;
1915         BOOL ret;
1916         DWORD bufSize = 0;
1917
1918         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1919          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1920          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1921         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1922         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1923          "Expected size >= %d, got %d\n",
1924            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1925         ok(buf != NULL, "Expected allocated buffer\n");
1926         if (buf)
1927         {
1928             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1929
1930             if (blob->cbData)
1931                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1932                  "Unexpected value\n");
1933             LocalFree(buf);
1934         }
1935     }
1936 }
1937
1938 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1939
1940 struct encodedBits
1941 {
1942     DWORD cUnusedBits;
1943     const BYTE *encoded;
1944     DWORD cbDecoded;
1945     const BYTE *decoded;
1946 };
1947
1948 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1949 static const unsigned char bin53[] = { 0xff,0xff };
1950 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1951 static const unsigned char bin55[] = { 0xff,0xfe };
1952 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1953 static const unsigned char bin57[] = { 0xfe };
1954 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1955
1956 static const struct encodedBits bits[] = {
1957     /* normal test cases */
1958     { 0, bin52, 2, bin53 },
1959     { 1, bin54, 2, bin55 },
1960     /* strange test case, showing cUnusedBits >= 8 is allowed */
1961     { 9, bin56, 1, bin57 },
1962     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1963     { 17, bin58, 0, NULL },
1964 };
1965
1966 static void test_encodeBits(DWORD dwEncoding)
1967 {
1968     DWORD i;
1969
1970     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1971     {
1972         CRYPT_BIT_BLOB blob;
1973         BOOL ret;
1974         BYTE *buf = NULL;
1975         DWORD bufSize = 0;
1976
1977         blob.cbData = sizeof(bytesToEncode);
1978         blob.pbData = (BYTE *)bytesToEncode;
1979         blob.cUnusedBits = bits[i].cUnusedBits;
1980         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1981          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1982         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1983         if (buf)
1984         {
1985             ok(bufSize == bits[i].encoded[1] + 2,
1986              "Got unexpected size %d, expected %d\n", bufSize,
1987              bits[i].encoded[1] + 2);
1988             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1989              "Unexpected value\n");
1990             LocalFree(buf);
1991         }
1992     }
1993 }
1994
1995 static void test_decodeBits(DWORD dwEncoding)
1996 {
1997     static const BYTE ber[] = "\x03\x02\x01\xff";
1998     static const BYTE berDecoded = 0xfe;
1999     DWORD i;
2000     BOOL ret;
2001     BYTE *buf = NULL;
2002     DWORD bufSize = 0;
2003
2004     /* normal cases */
2005     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2006     {
2007         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2008          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2009          &bufSize);
2010         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2011         if (buf)
2012         {
2013             CRYPT_BIT_BLOB *blob;
2014
2015             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2016                "Got unexpected size %d\n", bufSize);
2017             blob = (CRYPT_BIT_BLOB *)buf;
2018             ok(blob->cbData == bits[i].cbDecoded,
2019              "Got unexpected length %d, expected %d\n", blob->cbData,
2020              bits[i].cbDecoded);
2021             if (blob->cbData && bits[i].cbDecoded)
2022                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2023                  "Unexpected value\n");
2024             LocalFree(buf);
2025         }
2026     }
2027     /* special case: check that something that's valid in BER but not in DER
2028      * decodes successfully
2029      */
2030     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2031      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2032     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2033     if (buf)
2034     {
2035         CRYPT_BIT_BLOB *blob;
2036
2037         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2038            "Got unexpected size %d\n", bufSize);
2039         blob = (CRYPT_BIT_BLOB *)buf;
2040         ok(blob->cbData == sizeof(berDecoded),
2041            "Got unexpected length %d\n", blob->cbData);
2042         if (blob->cbData)
2043             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2044         LocalFree(buf);
2045     }
2046 }
2047
2048 struct Constraints2
2049 {
2050     CERT_BASIC_CONSTRAINTS2_INFO info;
2051     const BYTE *encoded;
2052 };
2053
2054 static const unsigned char bin59[] = { 0x30,0x00 };
2055 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2056 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2057 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2058 static const struct Constraints2 constraints2[] = {
2059  /* empty constraints */
2060  { { FALSE, FALSE, 0}, bin59 },
2061  /* can be a CA */
2062  { { TRUE,  FALSE, 0}, bin60 },
2063  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2064   * but that's not the case
2065   */
2066  { { FALSE, TRUE,  0}, bin61 },
2067  /* can be a CA and has path length constraints set */
2068  { { TRUE,  TRUE,  1}, bin62 },
2069 };
2070
2071 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2072 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2073  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2074  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2075  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2076 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2077  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2078  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2079  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2080  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2081
2082 static void test_encodeBasicConstraints(DWORD dwEncoding)
2083 {
2084     DWORD i, bufSize = 0;
2085     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2086     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2087      (LPBYTE)encodedDomainName };
2088     BOOL ret;
2089     BYTE *buf = NULL;
2090
2091     /* First test with the simpler info2 */
2092     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2093     {
2094         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2095          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2096          &bufSize);
2097         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2098         if (buf)
2099         {
2100             ok(bufSize == constraints2[i].encoded[1] + 2,
2101              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2102              bufSize);
2103             ok(!memcmp(buf, constraints2[i].encoded,
2104              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2105             LocalFree(buf);
2106         }
2107     }
2108     /* Now test with more complex basic constraints */
2109     info.SubjectType.cbData = 0;
2110     info.fPathLenConstraint = FALSE;
2111     info.cSubtreesConstraint = 0;
2112     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2113      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2114     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2115      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2116     if (buf)
2117     {
2118         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2119         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2120          "Unexpected value\n");
2121         LocalFree(buf);
2122     }
2123     /* None of the certs I examined had any subtree constraint, but I test one
2124      * anyway just in case.
2125      */
2126     info.cSubtreesConstraint = 1;
2127     info.rgSubtreesConstraint = &nameBlob;
2128     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2129      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2130     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2131      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2132     if (buf)
2133     {
2134         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2135         ok(!memcmp(buf, constraintWithDomainName,
2136          sizeof(constraintWithDomainName)), "Unexpected value\n");
2137         LocalFree(buf);
2138     }
2139     /* FIXME: test encoding with subject type. */
2140 }
2141
2142 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2143
2144 static void test_decodeBasicConstraints(DWORD dwEncoding)
2145 {
2146     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2147      0xff };
2148     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2149     DWORD i;
2150     BOOL ret;
2151     BYTE *buf = NULL;
2152     DWORD bufSize = 0;
2153
2154     /* First test with simpler info2 */
2155     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2156     {
2157         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2158          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2159          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2160         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2161          GetLastError());
2162         if (buf)
2163         {
2164             CERT_BASIC_CONSTRAINTS2_INFO *info =
2165              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2166
2167             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2168              "Unexpected value for item %d\n", i);
2169             LocalFree(buf);
2170         }
2171     }
2172     /* Check with the order of encoded elements inverted */
2173     buf = (PBYTE)1;
2174     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2175      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2176      &bufSize);
2177     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2178      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2179      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2180      GetLastError());
2181     ok(!buf, "Expected buf to be set to NULL\n");
2182     /* Check with a non-DER bool */
2183     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2184      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2185      (BYTE *)&buf, &bufSize);
2186     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2187     if (buf)
2188     {
2189         CERT_BASIC_CONSTRAINTS2_INFO *info =
2190          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2191
2192         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2193         LocalFree(buf);
2194     }
2195     /* Check with a non-basic constraints value */
2196     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2197      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2198      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2199     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2200      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2201      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2202      GetLastError());
2203     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2204     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2205      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2206      (BYTE *)&buf, &bufSize);
2207     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2208     if (buf)
2209     {
2210         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2211
2212         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2213         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2214         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2215         LocalFree(buf);
2216     }
2217     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2218      constraintWithDomainName, sizeof(constraintWithDomainName),
2219      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2220     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2221     if (buf)
2222     {
2223         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2224
2225         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2226         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2227         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2228         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2229         {
2230             ok(info->rgSubtreesConstraint[0].cbData ==
2231              sizeof(encodedDomainName), "Wrong size %d\n",
2232              info->rgSubtreesConstraint[0].cbData);
2233             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2234              sizeof(encodedDomainName)), "Unexpected value\n");
2235         }
2236         LocalFree(buf);
2237     }
2238 }
2239
2240 /* These are terrible public keys of course, I'm just testing encoding */
2241 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2242 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2243 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2244 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2245 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2246 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2248 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2249
2250 struct EncodedRSAPubKey
2251 {
2252     const BYTE *modulus;
2253     size_t modulusLen;
2254     const BYTE *encoded;
2255     size_t decodedModulusLen;
2256 };
2257
2258 struct EncodedRSAPubKey rsaPubKeys[] = {
2259     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2260     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2261     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2262     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2263 };
2264
2265 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2266 {
2267     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2268     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2269     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2270     BOOL ret;
2271     BYTE *buf = NULL;
2272     DWORD bufSize = 0, i;
2273
2274     /* Try with a bogus blob type */
2275     hdr->bType = 2;
2276     hdr->bVersion = CUR_BLOB_VERSION;
2277     hdr->reserved = 0;
2278     hdr->aiKeyAlg = CALG_RSA_KEYX;
2279     rsaPubKey->magic = 0x31415352;
2280     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2281     rsaPubKey->pubexp = 65537;
2282     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2283      sizeof(modulus1));
2284
2285     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2286      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2287      &bufSize);
2288     ok(!ret && GetLastError() == E_INVALIDARG,
2289      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2290     /* Now with a bogus reserved field */
2291     hdr->bType = PUBLICKEYBLOB;
2292     hdr->reserved = 1;
2293     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2294      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2295      &bufSize);
2296     if (buf)
2297     {
2298         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2299          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2300         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2301         LocalFree(buf);
2302     }
2303     /* Now with a bogus blob version */
2304     hdr->reserved = 0;
2305     hdr->bVersion = 0;
2306     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2307      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2308      &bufSize);
2309     if (buf)
2310     {
2311         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2312          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2313         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2314         LocalFree(buf);
2315     }
2316     /* And with a bogus alg ID */
2317     hdr->bVersion = CUR_BLOB_VERSION;
2318     hdr->aiKeyAlg = CALG_DES;
2319     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2320      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2321      &bufSize);
2322     if (buf)
2323     {
2324         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2325          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2326         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2327         LocalFree(buf);
2328     }
2329     /* Check a couple of RSA-related OIDs */
2330     hdr->aiKeyAlg = CALG_RSA_KEYX;
2331     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2332      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2333     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2334      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2335     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2336      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2337     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2338      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2339     /* Finally, all valid */
2340     hdr->aiKeyAlg = CALG_RSA_KEYX;
2341     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2342     {
2343         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2344          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2345         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2346          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2347         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2348         if (buf)
2349         {
2350             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2351              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2352              bufSize);
2353             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2354              "Unexpected value\n");
2355             LocalFree(buf);
2356         }
2357     }
2358 }
2359
2360 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2361 {
2362     DWORD i;
2363     LPBYTE buf = NULL;
2364     DWORD bufSize = 0;
2365     BOOL ret;
2366
2367     /* Try with a bad length */
2368     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2369      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2370      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2371     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2372      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2373      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2374      GetLastError());
2375     /* Try with a couple of RSA-related OIDs */
2376     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2377      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2378      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2379     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2380      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2381     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2382      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2383      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2384     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2385      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2386     /* Now try success cases */
2387     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2388     {
2389         bufSize = 0;
2390         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2391          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2392          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2393         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2394         if (buf)
2395         {
2396             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2397             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2398
2399             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2400              rsaPubKeys[i].decodedModulusLen,
2401              "Wrong size %d\n", bufSize);
2402             ok(hdr->bType == PUBLICKEYBLOB,
2403              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2404              hdr->bType);
2405             ok(hdr->bVersion == CUR_BLOB_VERSION,
2406              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2407              CUR_BLOB_VERSION, hdr->bVersion);
2408             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2409              hdr->reserved);
2410             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2411              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2412             ok(rsaPubKey->magic == 0x31415352,
2413              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2414             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2415              "Wrong bit len %d\n", rsaPubKey->bitlen);
2416             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2417              rsaPubKey->pubexp);
2418             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2419              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2420              "Unexpected modulus\n");
2421             LocalFree(buf);
2422         }
2423     }
2424 }
2425
2426 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2427  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2428  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2429
2430 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2431  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2432  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2433  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2434
2435 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2436 {
2437     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2438     CRYPT_SEQUENCE_OF_ANY seq;
2439     DWORD i;
2440     BOOL ret;
2441     BYTE *buf = NULL;
2442     DWORD bufSize = 0;
2443
2444     /* Encode a homogeneous sequence */
2445     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2446     {
2447         blobs[i].cbData = ints[i].encoded[1] + 2;
2448         blobs[i].pbData = (BYTE *)ints[i].encoded;
2449     }
2450     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2451     seq.rgValue = blobs;
2452
2453     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2454      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2455     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2456     if (buf)
2457     {
2458         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2459         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2460         LocalFree(buf);
2461     }
2462     /* Change the type of the first element in the sequence, and give it
2463      * another go
2464      */
2465     blobs[0].cbData = times[0].encodedTime[1] + 2;
2466     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2467     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2468      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2469     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2470     if (buf)
2471     {
2472         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2473         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2474          "Unexpected value\n");
2475         LocalFree(buf);
2476     }
2477 }
2478
2479 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2480 {
2481     BOOL ret;
2482     BYTE *buf = NULL;
2483     DWORD bufSize = 0;
2484
2485     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2486      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2487     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2488     if (buf)
2489     {
2490         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2491         DWORD i;
2492
2493         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2494          "Wrong elements %d\n", seq->cValue);
2495         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2496         {
2497             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2498              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2499              seq->rgValue[i].cbData);
2500             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2501              ints[i].encoded[1] + 2), "Unexpected value\n");
2502         }
2503         LocalFree(buf);
2504     }
2505     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2506      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2507      &bufSize);
2508     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2509     if (buf)
2510     {
2511         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2512
2513         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2514          "Wrong elements %d\n", seq->cValue);
2515         /* Just check the first element since it's all that changed */
2516         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2517          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2518          seq->rgValue[0].cbData);
2519         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2520          times[0].encodedTime[1] + 2), "Unexpected value\n");
2521         LocalFree(buf);
2522     }
2523 }
2524
2525 struct encodedExtensions
2526 {
2527     CERT_EXTENSIONS exts;
2528     const BYTE *encoded;
2529 };
2530
2531 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2532 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2533 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2534 static CERT_EXTENSION criticalExt =
2535  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2536 static CERT_EXTENSION nonCriticalExt =
2537  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2538
2539 static const BYTE ext0[] = { 0x30,0x00 };
2540 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2541                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2543                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2544
2545 static const struct encodedExtensions exts[] = {
2546  { { 0, NULL }, ext0 },
2547  { { 1, &criticalExt }, ext1 },
2548  { { 1, &nonCriticalExt }, ext2 },
2549 };
2550
2551 static void test_encodeExtensions(DWORD dwEncoding)
2552 {
2553     DWORD i;
2554
2555     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2556     {
2557         BOOL ret;
2558         BYTE *buf = NULL;
2559         DWORD bufSize = 0;
2560
2561         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2562          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2563         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2564         if (buf)
2565         {
2566             ok(bufSize == exts[i].encoded[1] + 2,
2567              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2568             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2569              "Unexpected value\n");
2570             LocalFree(buf);
2571         }
2572     }
2573 }
2574
2575 static void test_decodeExtensions(DWORD dwEncoding)
2576 {
2577     DWORD i;
2578
2579     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2580     {
2581         BOOL ret;
2582         BYTE *buf = NULL;
2583         DWORD bufSize = 0;
2584
2585         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2586          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2587          NULL, (BYTE *)&buf, &bufSize);
2588         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2589         if (buf)
2590         {
2591             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2592             DWORD j;
2593
2594             ok(ext->cExtension == exts[i].exts.cExtension,
2595              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2596              ext->cExtension);
2597             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2598             {
2599                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2600                  exts[i].exts.rgExtension[j].pszObjId),
2601                  "Expected OID %s, got %s\n",
2602                  exts[i].exts.rgExtension[j].pszObjId,
2603                  ext->rgExtension[j].pszObjId);
2604                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2605                  exts[i].exts.rgExtension[j].Value.pbData,
2606                  exts[i].exts.rgExtension[j].Value.cbData),
2607                  "Unexpected value\n");
2608             }
2609             LocalFree(buf);
2610         }
2611     }
2612 }
2613
2614 /* MS encodes public key info with a NULL if the algorithm identifier's
2615  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2616  * it encodes them by omitting the algorithm parameters.  This latter approach
2617  * seems more correct, so accept either form.
2618  */
2619 struct encodedPublicKey
2620 {
2621     CERT_PUBLIC_KEY_INFO info;
2622     const BYTE *encoded;
2623     const BYTE *encodedNoNull;
2624     CERT_PUBLIC_KEY_INFO decoded;
2625 };
2626
2627 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2628  0xe, 0xf };
2629 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2630
2631 static const unsigned char bin64[] = {
2632     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2633 static const unsigned char bin65[] = {
2634     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2635 static const unsigned char bin66[] = {
2636     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2637 static const unsigned char bin67[] = {
2638     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2639 static const unsigned char bin68[] = {
2640     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2641     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2642 static const unsigned char bin69[] = {
2643     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2644     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2645 static const unsigned char bin70[] = {
2646     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2647     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2648     0x0f};
2649 static const unsigned char bin71[] = {
2650     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2651     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2652     0x0f};
2653 static unsigned char bin72[] = { 0x05,0x00};
2654
2655 static CHAR oid_bogus[] = "1.2.3",
2656             oid_rsa[]   = szOID_RSA;
2657
2658 static const struct encodedPublicKey pubKeys[] = {
2659  /* with a bogus OID */
2660  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2661   bin64, bin65,
2662   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2663  /* some normal keys */
2664  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2665   bin66, bin67,
2666   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2667  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2668   bin68, bin69,
2669   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2670  /* with add'l parameters--note they must be DER-encoded */
2671  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2672   (BYTE *)aKey, 0 } },
2673   bin70, bin71,
2674   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2675   (BYTE *)aKey, 0 } } },
2676 };
2677
2678 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2679 {
2680     DWORD i;
2681
2682     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2683     {
2684         BOOL ret;
2685         BYTE *buf = NULL;
2686         DWORD bufSize = 0;
2687
2688         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2689          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2690          &bufSize);
2691         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2692          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2693         if (buf)
2694         {
2695             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2696              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2697              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2698              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2699             if (bufSize == pubKeys[i].encoded[1] + 2)
2700                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2701                  "Unexpected value\n");
2702             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2703                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2704                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2705             LocalFree(buf);
2706         }
2707     }
2708 }
2709
2710 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2711  const CERT_PUBLIC_KEY_INFO *got)
2712 {
2713     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2714      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2715      got->Algorithm.pszObjId);
2716     ok(expected->Algorithm.Parameters.cbData ==
2717      got->Algorithm.Parameters.cbData,
2718      "Expected parameters of %d bytes, got %d\n",
2719      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2720     if (expected->Algorithm.Parameters.cbData)
2721         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2722          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2723          "Unexpected algorithm parameters\n");
2724     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2725      "Expected public key of %d bytes, got %d\n",
2726      expected->PublicKey.cbData, got->PublicKey.cbData);
2727     if (expected->PublicKey.cbData)
2728         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2729          got->PublicKey.cbData), "Unexpected public key value\n");
2730 }
2731
2732 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2733 {
2734     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2735      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2736      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2737      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2738     DWORD i;
2739     BOOL ret;
2740     BYTE *buf = NULL;
2741     DWORD bufSize = 0;
2742
2743     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2744     {
2745         /* The NULL form decodes to the decoded member */
2746         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2747          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2748          NULL, (BYTE *)&buf, &bufSize);
2749         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2750         if (buf)
2751         {
2752             comparePublicKeyInfo(&pubKeys[i].decoded,
2753              (CERT_PUBLIC_KEY_INFO *)buf);
2754             LocalFree(buf);
2755         }
2756         /* The non-NULL form decodes to the original */
2757         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2758          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2759          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2760         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2761         if (buf)
2762         {
2763             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2764             LocalFree(buf);
2765         }
2766     }
2767     /* Test with bogus (not valid DER) parameters */
2768     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2769      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2770      NULL, (BYTE *)&buf, &bufSize);
2771     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2772      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2773      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2774      GetLastError());
2775 }
2776
2777 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2778  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2779  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2780  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2781  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2782 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2783  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2784  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2785  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2786  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2787 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2788  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2789  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2790  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2791  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2792 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2793  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2794  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2795  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2796  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2797  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2798  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2799 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2800  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2801  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2802  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2803  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2804  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2805  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2806 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2807  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2808  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2809  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2810  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2811  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2812  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2813  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2814  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2815  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2816 static const BYTE v1CertWithPubKey[] = {
2817 0x30,0x81,0x95,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,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2824 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2825 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2826 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2827 0x01,0x01 };
2828 static const BYTE v1CertWithPubKeyNoNull[] = {
2829 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2830 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2831 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2832 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2833 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2834 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2835 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2836 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2837 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2838 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2839 static const BYTE v1CertWithSubjectKeyId[] = {
2840 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2841 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2842 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2843 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2844 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2845 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2846 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2847 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2848 0x4c,0x61,0x6e,0x67,0x00 };
2849
2850 static const BYTE serialNum[] = { 0x01 };
2851
2852 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2853 {
2854     BOOL ret;
2855     BYTE *buf = NULL;
2856     DWORD size = 0;
2857     CERT_INFO info = { 0 };
2858     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2859     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2860     CERT_EXTENSION ext;
2861
2862     if (0)
2863     {
2864         /* Test with NULL pvStructInfo (crashes on win9x) */
2865         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2866          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2867         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2868          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2869     }
2870     /* Test with a V1 cert */
2871     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2872      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2873     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2874      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2875     if (buf)
2876     {
2877         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2878          v1Cert[1] + 2, size);
2879         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2880         LocalFree(buf);
2881     }
2882     /* Test v2 cert */
2883     info.dwVersion = CERT_V2;
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(v2Cert), "Wrong size %d\n", size);
2891         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2892         LocalFree(buf);
2893     }
2894     /* Test v3 cert */
2895     info.dwVersion = CERT_V3;
2896     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2897      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2898     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2899      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2900     if (buf)
2901     {
2902         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2903         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2904         LocalFree(buf);
2905     }
2906     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2907      * API doesn't prevent it)
2908      */
2909     info.dwVersion = CERT_V1;
2910     info.cExtension = 1;
2911     info.rgExtension = &criticalExt;
2912     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2913      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2914     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2915      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2916     if (buf)
2917     {
2918         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2919         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2920         LocalFree(buf);
2921     }
2922     /* test v1 cert with a serial number */
2923     info.SerialNumber.cbData = sizeof(serialNum);
2924     info.SerialNumber.pbData = (BYTE *)serialNum;
2925     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2926      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2927     if (buf)
2928     {
2929         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2930         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2931         LocalFree(buf);
2932     }
2933     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2934     info.Issuer.cbData = sizeof(encodedCommonName);
2935     info.Issuer.pbData = (BYTE *)encodedCommonName;
2936     info.Subject.cbData = sizeof(encodedCommonName);
2937     info.Subject.pbData = (BYTE *)encodedCommonName;
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(bigCert), "Wrong size %d\n", size);
2943         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2944         LocalFree(buf);
2945     }
2946     /* Add a public key */
2947     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2948     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2949     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2950     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2951      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2952     if (buf)
2953     {
2954         ok(size == sizeof(v1CertWithPubKey) ||
2955          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2956         if (size == sizeof(v1CertWithPubKey))
2957             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2958         else if (size == sizeof(v1CertWithPubKeyNoNull))
2959             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2960              "Got unexpected value\n");
2961         LocalFree(buf);
2962     }
2963     /* Remove the public key, and add a subject key identifier extension */
2964     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2965     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2966     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2967     ext.pszObjId = oid_subject_key_identifier;
2968     ext.fCritical = FALSE;
2969     ext.Value.cbData = sizeof(octetCommonNameValue);
2970     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2971     info.cExtension = 1;
2972     info.rgExtension = &ext;
2973     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2974      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2975     if (buf)
2976     {
2977         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2978         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2979         LocalFree(buf);
2980     }
2981 }
2982
2983 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2984 {
2985     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2986      v1CertWithConstraints, v1CertWithSerial };
2987     BOOL ret;
2988     BYTE *buf = NULL;
2989     DWORD size = 0, i;
2990
2991     /* Test with NULL pbEncoded */
2992     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2993      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2994     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2995      GetLastError() == OSS_BAD_ARG /* Win9x */),
2996      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2997     if (0)
2998     {
2999         /* Crashes on win9x */
3000         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3001          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3002         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3003          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3004     }
3005     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3006      * minimum a cert must have a non-zero serial number, an issuer, and a
3007      * subject.
3008      */
3009     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3010     {
3011         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3012          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3013          (BYTE *)&buf, &size);
3014         ok(!ret, "Expected failure\n");
3015     }
3016     /* Now check with serial number, subject and issuer specified */
3017     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3018      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3019     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3020     if (buf)
3021     {
3022         CERT_INFO *info = (CERT_INFO *)buf;
3023
3024         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3025         ok(info->SerialNumber.cbData == 1,
3026          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3027         ok(*info->SerialNumber.pbData == *serialNum,
3028          "Expected serial number %d, got %d\n", *serialNum,
3029          *info->SerialNumber.pbData);
3030         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3031          "Wrong size %d\n", info->Issuer.cbData);
3032         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3033          "Unexpected issuer\n");
3034         ok(info->Subject.cbData == sizeof(encodedCommonName),
3035          "Wrong size %d\n", info->Subject.cbData);
3036         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3037          info->Subject.cbData), "Unexpected subject\n");
3038         LocalFree(buf);
3039     }
3040     /* Check again with pub key specified */
3041     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3042      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3043      (BYTE *)&buf, &size);
3044     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3045     if (buf)
3046     {
3047         CERT_INFO *info = (CERT_INFO *)buf;
3048
3049         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3050         ok(info->SerialNumber.cbData == 1,
3051          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3052         ok(*info->SerialNumber.pbData == *serialNum,
3053          "Expected serial number %d, got %d\n", *serialNum,
3054          *info->SerialNumber.pbData);
3055         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3056          "Wrong size %d\n", info->Issuer.cbData);
3057         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3058          "Unexpected issuer\n");
3059         ok(info->Subject.cbData == sizeof(encodedCommonName),
3060          "Wrong size %d\n", info->Subject.cbData);
3061         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3062          info->Subject.cbData), "Unexpected subject\n");
3063         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3064          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3065          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3066         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3067          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3068         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3069          sizeof(aKey)), "Unexpected public key\n");
3070         LocalFree(buf);
3071     }
3072 }
3073
3074 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3075  0xe, 0xf };
3076
3077 static const BYTE signedBigCert[] = {
3078  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3079  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3080  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3081  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3082  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3083  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3084  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3085  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3086  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3087  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3088  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3089  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3090
3091 static void test_encodeCert(DWORD dwEncoding)
3092 {
3093     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3094      * also that bigCert is a NULL-terminated string, so don't count its
3095      * last byte (otherwise the signed cert won't decode.)
3096      */
3097     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3098      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3099     BOOL ret;
3100     BYTE *buf = NULL;
3101     DWORD bufSize = 0;
3102
3103     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3104      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3106     if (buf)
3107     {
3108         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3109         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3110         LocalFree(buf);
3111     }
3112 }
3113
3114 static void test_decodeCert(DWORD dwEncoding)
3115 {
3116     BOOL ret;
3117     BYTE *buf = NULL;
3118     DWORD size = 0;
3119
3120     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3121      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3122     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3123     if (buf)
3124     {
3125         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3126
3127         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3128          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3129         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3130          "Unexpected cert\n");
3131         ok(info->Signature.cbData == sizeof(hash),
3132          "Wrong signature size %d\n", info->Signature.cbData);
3133         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3134          "Unexpected signature\n");
3135         LocalFree(buf);
3136     }
3137     /* A signed cert decodes as a CERT_INFO too */
3138     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3139      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3140     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3141     if (buf)
3142     {
3143         CERT_INFO *info = (CERT_INFO *)buf;
3144
3145         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3146         ok(info->SerialNumber.cbData == 1,
3147          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3148         ok(*info->SerialNumber.pbData == *serialNum,
3149          "Expected serial number %d, got %d\n", *serialNum,
3150          *info->SerialNumber.pbData);
3151         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3152          "Wrong size %d\n", info->Issuer.cbData);
3153         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3154          "Unexpected issuer\n");
3155         ok(info->Subject.cbData == sizeof(encodedCommonName),
3156          "Wrong size %d\n", info->Subject.cbData);
3157         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3158          info->Subject.cbData), "Unexpected subject\n");
3159         LocalFree(buf);
3160     }
3161 }
3162
3163 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3164 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3165  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3166  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3167 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3168  0x00, 0x03 };
3169 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3170  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3171  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3172 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3173  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3174  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3175  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3176  0x2e, 0x6f, 0x72, 0x67 };
3177 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3178  CRL_REASON_AFFILIATION_CHANGED;
3179
3180 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3181 {
3182     CRL_DIST_POINTS_INFO info = { 0 };
3183     CRL_DIST_POINT point = { { 0 } };
3184     CERT_ALT_NAME_ENTRY entry = { 0 };
3185     BOOL ret;
3186     BYTE *buf = NULL;
3187     DWORD size = 0;
3188
3189     /* Test with an empty info */
3190     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3191      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3192     ok(!ret && GetLastError() == E_INVALIDARG,
3193      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3194     /* Test with one empty dist point */
3195     info.cDistPoint = 1;
3196     info.rgDistPoint = &point;
3197     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3198      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3199     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3200     if (buf)
3201     {
3202         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3203         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3204         LocalFree(buf);
3205     }
3206     /* A dist point with an invalid name */
3207     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3208     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3209     U(entry).pwszURL = (LPWSTR)nihongoURL;
3210     U(point.DistPointName).FullName.cAltEntry = 1;
3211     U(point.DistPointName).FullName.rgAltEntry = &entry;
3212     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3213      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3214     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3215      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3216     /* The first invalid character is at index 7 */
3217     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3218      "Expected invalid char at index 7, got %d\n",
3219      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3220     /* A dist point with (just) a valid name */
3221     U(entry).pwszURL = (LPWSTR)url;
3222     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3223      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3224     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3225     if (buf)
3226     {
3227         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3228         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3229         LocalFree(buf);
3230     }
3231     /* A dist point with (just) reason flags */
3232     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3233     point.ReasonFlags.cbData = sizeof(crlReason);
3234     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3235     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3236      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3237     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3238     if (buf)
3239     {
3240         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3241         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3242         LocalFree(buf);
3243     }
3244     /* A dist point with just an issuer */
3245     point.ReasonFlags.cbData = 0;
3246     point.CRLIssuer.cAltEntry = 1;
3247     point.CRLIssuer.rgAltEntry = &entry;
3248     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3249      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3250     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3251     if (buf)
3252     {
3253         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3254         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3255         LocalFree(buf);
3256     }
3257     /* A dist point with both a name and an issuer */
3258     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3259     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3260      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3261     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3262     if (buf)
3263     {
3264         ok(size == sizeof(distPointWithUrlAndIssuer),
3265          "Wrong size %d\n", size);
3266         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3267         LocalFree(buf);
3268     }
3269 }
3270
3271 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3272 {
3273     BOOL ret;
3274     BYTE *buf = NULL;
3275     DWORD size = 0;
3276     PCRL_DIST_POINTS_INFO info;
3277     PCRL_DIST_POINT point;
3278     PCERT_ALT_NAME_ENTRY entry;
3279
3280     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3281      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3282      (BYTE *)&buf, &size);
3283     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
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 == CRL_DIST_POINT_NO_NAME,
3293          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3294          point->DistPointName.dwDistPointNameChoice);
3295         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3296         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3297         LocalFree(buf);
3298     }
3299     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3300      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3301      (BYTE *)&buf, &size);
3302     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3303     if (ret)
3304     {
3305         info = (PCRL_DIST_POINTS_INFO)buf;
3306         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3307          "Wrong size %d\n", size);
3308         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3309          info->cDistPoint);
3310         point = info->rgDistPoint;
3311         ok(point->DistPointName.dwDistPointNameChoice ==
3312          CRL_DIST_POINT_FULL_NAME,
3313          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3314          point->DistPointName.dwDistPointNameChoice);
3315         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3316          "Expected 1 name entry, got %d\n",
3317          U(point->DistPointName).FullName.cAltEntry);
3318         entry = U(point->DistPointName).FullName.rgAltEntry;
3319         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3320          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3321         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3322         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3323         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3324         LocalFree(buf);
3325     }
3326     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3327      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3328      NULL, (BYTE *)&buf, &size);
3329     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3330     if (ret)
3331     {
3332         info = (PCRL_DIST_POINTS_INFO)buf;
3333         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3334          "Wrong size %d\n", size);
3335         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3336          info->cDistPoint);
3337         point = info->rgDistPoint;
3338         ok(point->DistPointName.dwDistPointNameChoice ==
3339          CRL_DIST_POINT_NO_NAME,
3340          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3341          point->DistPointName.dwDistPointNameChoice);
3342         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3343          "Expected reason length\n");
3344         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3345          "Unexpected reason\n");
3346         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3347         LocalFree(buf);
3348     }
3349     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3350      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3351      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3352     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3353     if (ret)
3354     {
3355         info = (PCRL_DIST_POINTS_INFO)buf;
3356         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3357          "Wrong size %d\n", size);
3358         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3359          info->cDistPoint);
3360         point = info->rgDistPoint;
3361         ok(point->DistPointName.dwDistPointNameChoice ==
3362          CRL_DIST_POINT_FULL_NAME,
3363          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3364          point->DistPointName.dwDistPointNameChoice);
3365         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3366          "Expected 1 name entry, got %d\n",
3367          U(point->DistPointName).FullName.cAltEntry);
3368         entry = U(point->DistPointName).FullName.rgAltEntry;
3369         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3370          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3371         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3372         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3373         ok(point->CRLIssuer.cAltEntry == 1,
3374          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3375         entry = point->CRLIssuer.rgAltEntry;
3376         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3377          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3378         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3379         LocalFree(buf);
3380     }
3381 }
3382
3383 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3384 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3385 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3386  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3387  0x67 };
3388
3389 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3390 {
3391     BOOL ret;
3392     BYTE *buf = NULL;
3393     DWORD size = 0;
3394     CRL_ISSUING_DIST_POINT point = { { 0 } };
3395     CERT_ALT_NAME_ENTRY entry;
3396
3397     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3398      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3399     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3400     {
3401         skip("no X509_ISSUING_DIST_POINT encode support\n");
3402         return;
3403     }
3404     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3405      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3406     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3407      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3408     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3409     if (buf)
3410     {
3411         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3412         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3413         LocalFree(buf);
3414     }
3415     /* nonsensical flags */
3416     point.fOnlyContainsUserCerts = TRUE;
3417     point.fOnlyContainsCACerts = TRUE;
3418     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3419      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3420     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3421     if (buf)
3422     {
3423         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3424         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3425         LocalFree(buf);
3426     }
3427     /* unimplemented name type */
3428     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3429     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3430     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3431      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3432     ok(!ret && GetLastError() == E_INVALIDARG,
3433      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3434     /* empty name */
3435     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3436     U(point.DistPointName).FullName.cAltEntry = 0;
3437     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3438      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3439     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3440     if (buf)
3441     {
3442         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3443         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3444         LocalFree(buf);
3445     }
3446     /* name with URL entry */
3447     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3448     U(entry).pwszURL = (LPWSTR)url;
3449     U(point.DistPointName).FullName.cAltEntry = 1;
3450     U(point.DistPointName).FullName.rgAltEntry = &entry;
3451     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3452      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3453     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3454     if (buf)
3455     {
3456         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3457         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3458         LocalFree(buf);
3459     }
3460 }
3461
3462 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3463  const CERT_ALT_NAME_ENTRY *got)
3464 {
3465     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3466      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3467      got->dwAltNameChoice);
3468     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3469     {
3470         switch (got->dwAltNameChoice)
3471         {
3472         case CERT_ALT_NAME_RFC822_NAME:
3473         case CERT_ALT_NAME_DNS_NAME:
3474         case CERT_ALT_NAME_EDI_PARTY_NAME:
3475         case CERT_ALT_NAME_URL:
3476         case CERT_ALT_NAME_REGISTERED_ID:
3477             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3478              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3479              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3480              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3481              "Unexpected name\n");
3482             break;
3483         case CERT_ALT_NAME_X400_ADDRESS:
3484         case CERT_ALT_NAME_DIRECTORY_NAME:
3485         case CERT_ALT_NAME_IP_ADDRESS:
3486             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3487                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3488             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3489                        U(*got).IPAddress.cbData), "Unexpected value\n");
3490             break;
3491         }
3492     }
3493 }
3494
3495 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3496  const CERT_ALT_NAME_INFO *got)
3497 {
3498     DWORD i;
3499
3500     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3501      expected->cAltEntry, got->cAltEntry);
3502     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3503         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3504 }
3505
3506 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3507  const CRL_DIST_POINT_NAME *got)
3508 {
3509     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3510      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3511     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3512         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3513 }
3514
3515 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3516  const CRL_ISSUING_DIST_POINT *got)
3517 {
3518     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3519     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3520      "Unexpected fOnlyContainsUserCerts\n");
3521     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3522      "Unexpected fOnlyContainsCACerts\n");
3523     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3524      "Unexpected reason flags\n");
3525     ok(got->fIndirectCRL == expected->fIndirectCRL,
3526      "Unexpected fIndirectCRL\n");
3527 }
3528
3529 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3530 {
3531     BOOL ret;
3532     BYTE *buf = NULL;
3533     DWORD size = 0;
3534     CRL_ISSUING_DIST_POINT point = { { 0 } };
3535
3536     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3537      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3538      (BYTE *)&buf, &size);
3539     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3540     {
3541         skip("no X509_ISSUING_DIST_POINT decode support\n");
3542         return;
3543     }
3544     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3545     if (ret)
3546     {
3547         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3548         LocalFree(buf);
3549     }
3550     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3551      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3552      (BYTE *)&buf, &size);
3553     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3554     if (ret)
3555     {
3556         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3557         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3558         LocalFree(buf);
3559     }
3560     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3561      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3562      (BYTE *)&buf, &size);
3563     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3564     if (ret)
3565     {
3566         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3567         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3568         U(point.DistPointName).FullName.cAltEntry = 0;
3569         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3570         LocalFree(buf);
3571     }
3572     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3573      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3574     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3575     if (ret)
3576     {
3577         CERT_ALT_NAME_ENTRY entry;
3578
3579         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3580         U(entry).pwszURL = (LPWSTR)url;
3581         U(point.DistPointName).FullName.cAltEntry = 1;
3582         U(point.DistPointName).FullName.rgAltEntry = &entry;
3583         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3584         LocalFree(buf);
3585     }
3586 }
3587
3588 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3589  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3590  0x30, 0x5a };
3591 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3592  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3593  0x30, 0x30, 0x30, 0x30, 0x5a };
3594 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3595  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3596  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3597  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3598  0x5a };
3599 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3600  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3601  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3602  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3603  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3604  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3605 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3606  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3607  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3608  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3609  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3610  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3611 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3612  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3613  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3614  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3615  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3616  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3617  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3618 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3619  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3620  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3621  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3622  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3623  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3624  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3625 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3626  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3627  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3628  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3629  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3630  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3631  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3632 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3633  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3634  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3635  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3636  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3637  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3638  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3639
3640 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3641 {
3642     BOOL ret;
3643     BYTE *buf = NULL;
3644     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3645     DWORD size = 0;
3646     CRL_INFO info = { 0 };
3647     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3648     CERT_EXTENSION ext;
3649
3650     /* Test with a V1 CRL */
3651     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3652      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3653     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3654      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3655     if (buf)
3656     {
3657         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3658         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3659         LocalFree(buf);
3660     }
3661     /* Test v2 CRL */
3662     info.dwVersion = CRL_V2;
3663     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3664      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3665     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3666      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3667     if (buf)
3668     {
3669         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3670          v2CRL[1] + 2, size);
3671         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3672         LocalFree(buf);
3673     }
3674     /* v1 CRL with a name */
3675     info.dwVersion = CRL_V1;
3676     info.Issuer.cbData = sizeof(encodedCommonName);
3677     info.Issuer.pbData = (BYTE *)encodedCommonName;
3678     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3679      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3680     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3681     if (buf)
3682     {
3683         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3684         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3685         LocalFree(buf);
3686     }
3687     if (0)
3688     {
3689         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3690         info.cCRLEntry = 1;
3691         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3692          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3693         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3694          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3695     }
3696     /* now set an empty entry */
3697     info.cCRLEntry = 1;
3698     info.rgCRLEntry = &entry;
3699     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3700      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3701     if (buf)
3702     {
3703         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3704          "Wrong size %d\n", size);
3705         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3706          "Got unexpected value\n");
3707         LocalFree(buf);
3708     }
3709     /* an entry with a serial number */
3710     entry.SerialNumber.cbData = sizeof(serialNum);
3711     entry.SerialNumber.pbData = (BYTE *)serialNum;
3712     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3713      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3714     if (buf)
3715     {
3716         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3717          "Wrong size %d\n", size);
3718         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3719          "Got unexpected value\n");
3720         LocalFree(buf);
3721     }
3722     /* an entry with an extension */
3723     entry.cExtension = 1;
3724     entry.rgExtension = &criticalExt;
3725     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3726      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3727     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3728     if (buf)
3729     {
3730         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3731         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3732         LocalFree(buf);
3733     }
3734     /* a CRL with an extension */
3735     entry.cExtension = 0;
3736     info.cExtension = 1;
3737     info.rgExtension = &criticalExt;
3738     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3739      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3740     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3741     if (buf)
3742     {
3743         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3744         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3745         LocalFree(buf);
3746     }
3747     /* a v2 CRL with an extension, this time non-critical */
3748     info.dwVersion = CRL_V2;
3749     info.rgExtension = &nonCriticalExt;
3750     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3751      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3752     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3753     if (buf)
3754     {
3755         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3756         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3757         LocalFree(buf);
3758     }
3759     /* a v2 CRL with an issuing dist point extension */
3760     ext.pszObjId = oid_issuing_dist_point;
3761     ext.fCritical = TRUE;
3762     ext.Value.cbData = sizeof(urlIDP);
3763     ext.Value.pbData = (LPBYTE)urlIDP;
3764     entry.rgExtension = &ext;
3765     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3766      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3768     if (buf)
3769     {
3770         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3771         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3772         LocalFree(buf);
3773     }
3774 }
3775
3776 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3777  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3778  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3779  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3780  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3781  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3782  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3783  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3784  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3785  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3786  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3787  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3788  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3789  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3790  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3791  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3792  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3793  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3794  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3795  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3796  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3797  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3798  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3799  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3800  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3801  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3802  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3803  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3804  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3805  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3806  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3807  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3808  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3809  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3810  0xcd };
3811 static const BYTE verisignCRLWithLotsOfEntries[] = {
3812 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3813 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3814 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3815 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3816 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3817 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3818 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3819 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3820 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3821 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3822 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3823 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3824 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3825 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3826 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3827 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3828 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3829 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3830 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3831 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3832 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3833 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3834 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3835 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3836 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3837 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3838 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3839 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3840 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3841 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3842 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3843 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3844 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3845 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3846 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3847 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3848 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3849 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3850 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3851 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3852 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3853 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3854 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3855 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3856 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3857 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3858 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3859 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3860 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3861 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3862 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3863 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3864 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3865 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3866 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3867 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3868 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3869 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3870 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3871 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3872 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3873 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3874 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3875 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3876 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3877 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3878 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3879 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3880 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3881 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3882 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3883 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3884 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3885 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3886 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3887 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3888 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3889 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3890 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3891 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3892 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3893 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3894 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3895 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3896 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3897 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3898 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3899 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3900 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3901 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3902 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3903 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3904 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3905 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3906 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3907 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3908 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3909 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3910 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3911 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3912 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3913 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3914 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3915 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3916 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3917 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3918 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3919 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3920 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3921 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3922 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3923 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3924 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3925 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3926 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3927 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3928 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3929 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3930 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3931 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3932 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3933 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3934 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3935 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3936 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3937 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3938 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3939 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3940 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3941 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3942 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3943 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3944 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3945 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3946 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3947 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3948 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3949 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3950 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3951 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3952 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3953 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3954 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3955 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3956 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3957 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3958 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3959 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3960 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3961 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3962 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3963 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3964 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3965 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3966 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3967 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3968 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3969 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3970 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3971 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3972 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3973 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3974 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3975 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3976 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3977 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3978 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3979 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3980 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3981 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3982 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3983 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3984 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3985 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3986 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3987 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3988 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3989 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3990 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3991 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3992 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3993 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3994 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3995 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3996 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3997 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3998 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3999 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4000 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4001 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4002 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4003 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4004 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4005 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4006 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4007 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4008 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4009 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4010 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4011 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4012 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4013 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4014 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4015 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4016 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4017 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4018 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4019 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4020 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4021 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4022 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4023 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4024 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4025 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4026 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4027 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4028 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4029 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4030 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4031 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4032 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4033 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4034 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4035 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4036 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4037 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4038 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4039 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4040 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4041 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4042 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4043 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4044 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4045 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4046 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4047 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4048 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4049 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4050 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4051 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4052 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4053 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4054 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4055 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4056 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4057 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4058 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4059 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4060 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4061 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4062 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4063 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4064 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4065 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4066 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4067 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4068 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4069 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4070 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4071 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4072 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4073 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4074 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4075 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4076 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4077 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4078 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4079 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4080 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4081 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4082 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4083 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4084 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4085 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4086 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4087 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4088 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4089 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4090 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4091 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4092 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4093 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4094 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4095 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4096 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4097 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4098 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4099 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4100 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4101 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4102 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4103 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4104 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4105 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4106 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4107 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4108 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4109 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4110 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4111 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4112 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4113 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4114 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4115 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4116 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4117 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4118 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4119 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4120 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4121 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4122 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4123 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4124 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4125 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4126 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4127 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4128 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4129 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4130 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4131 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4132 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4133 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4134 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4135 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4136 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4137 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4138 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4139 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4140 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4141 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4142 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4143 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4144 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4145 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4146 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4147 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4148 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4149 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4150 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4151 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4152 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4153 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4154 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4155 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4156 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4157 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4158 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4159 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4160 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4161 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4162 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4163 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4164 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4165 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4166 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4167 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4168 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4169 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4170 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4171 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4172 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4173 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4174 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4175 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4176 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4177 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4178 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4179 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4180 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4181 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4182 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4183 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4184 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4185 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4186 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4187 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4188 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4189 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4190 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4191 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4192 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4193 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4194 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4195 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4196 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4197 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4198 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4199 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4200 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4201 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4202 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4203 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4204 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4205 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4206 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4207 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4208 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4209 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4210 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4211 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4212 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4213 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4214 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4215 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4216 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4217 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4218 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4219 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4220 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4221 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4222 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4223 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4224 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4225 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4226 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4227 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4228 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4229 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4230 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4231 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4232 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4233 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4234 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4235 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4236 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4237 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4238 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4239 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4240 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4241 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4242 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4243 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4244 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4245 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4246 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4247 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4248 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4249 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4250 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4251 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4252 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4253 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4254 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4255 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4256 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4257 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4258 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4259 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4260 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4261 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4262 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4263 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4264 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4265 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4266 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4267 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4268 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4269 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4270 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4271 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4272 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4273 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4274 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4275 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4276 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4277 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4278 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4279 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4280 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4281 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4282 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4283 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4284 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4285 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4286 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4287 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4288 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4289 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4290 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4291 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4292 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4293 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4294 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4295 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4296 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4297 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4298 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4299 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4300 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4301 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4302 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4303 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4304 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4305 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4306 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4307 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4308 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4309 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4310 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4311 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4312 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4313 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4314 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4315 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4316 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4317 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4318 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4319 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4320
4321 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4322 {
4323     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4324     BOOL ret;
4325     BYTE *buf = NULL;
4326     DWORD size = 0, i;
4327
4328     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4329     {
4330         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4331          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4332          (BYTE *)&buf, &size);
4333         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4334          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4335          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4336          GetLastError());
4337     }
4338     /* at a minimum, a CRL must contain an issuer: */
4339     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4340      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4341      (BYTE *)&buf, &size);
4342     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4343     if (buf)
4344     {
4345         CRL_INFO *info = (CRL_INFO *)buf;
4346
4347         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4348         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4349          info->cCRLEntry);
4350         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4351          "Wrong issuer size %d\n", info->Issuer.cbData);
4352         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4353          "Unexpected issuer\n");
4354         LocalFree(buf);
4355     }
4356     /* check decoding with an empty CRL entry */
4357     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4358      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4359      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4360     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4361      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4362      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4363      GetLastError());
4364     /* with a real CRL entry */
4365     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4366      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4367      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4368     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4369     if (buf)
4370     {
4371         CRL_INFO *info = (CRL_INFO *)buf;
4372         CRL_ENTRY *entry;
4373
4374         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4375         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4376          info->cCRLEntry);
4377         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4378         entry = info->rgCRLEntry;
4379         ok(entry->SerialNumber.cbData == 1,
4380          "Expected serial number size 1, got %d\n",
4381          entry->SerialNumber.cbData);
4382         ok(*entry->SerialNumber.pbData == *serialNum,
4383          "Expected serial number %d, got %d\n", *serialNum,
4384          *entry->SerialNumber.pbData);
4385         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4386          "Wrong issuer size %d\n", info->Issuer.cbData);
4387         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4388          "Unexpected issuer\n");
4389         LocalFree(buf);
4390     }
4391     /* a real CRL from verisign that has extensions */
4392     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4393      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4394      NULL, (BYTE *)&buf, &size);
4395     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4396     if (buf)
4397     {
4398         CRL_INFO *info = (CRL_INFO *)buf;
4399         CRL_ENTRY *entry;
4400
4401         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4402         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4403          info->cCRLEntry);
4404         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4405         entry = info->rgCRLEntry;
4406         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4407          info->cExtension);
4408         LocalFree(buf);
4409     }
4410     /* another real CRL from verisign that has lots of entries */
4411     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4412      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4413      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4414     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4415     if (buf)
4416     {
4417         CRL_INFO *info = (CRL_INFO *)buf;
4418
4419         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4420         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4421          info->cCRLEntry);
4422         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4423          info->cExtension);
4424         LocalFree(buf);
4425     }
4426     /* and finally, with an extension */
4427     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4428      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4429      NULL, (BYTE *)&buf, &size);
4430     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4431     if (buf)
4432     {
4433         CRL_INFO *info = (CRL_INFO *)buf;
4434         CRL_ENTRY *entry;
4435
4436         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4437         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4438          info->cCRLEntry);
4439         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4440         entry = info->rgCRLEntry;
4441         ok(entry->SerialNumber.cbData == 1,
4442          "Expected serial number size 1, got %d\n",
4443          entry->SerialNumber.cbData);
4444         ok(*entry->SerialNumber.pbData == *serialNum,
4445          "Expected serial number %d, got %d\n", *serialNum,
4446          *entry->SerialNumber.pbData);
4447         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4448          "Wrong issuer size %d\n", info->Issuer.cbData);
4449         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4450          "Unexpected issuer\n");
4451         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4452          info->cExtension);
4453         LocalFree(buf);
4454     }
4455     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4456      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4457      NULL, (BYTE *)&buf, &size);
4458     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4459     if (buf)
4460     {
4461         CRL_INFO *info = (CRL_INFO *)buf;
4462
4463         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4464          info->cExtension);
4465         LocalFree(buf);
4466     }
4467     /* And again, with an issuing dist point */
4468     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4469      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4470      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4471     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4472     if (buf)
4473     {
4474         CRL_INFO *info = (CRL_INFO *)buf;
4475
4476         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4477          info->cExtension);
4478         LocalFree(buf);
4479     }
4480 }
4481
4482 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4483  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4484 static const BYTE encodedUsage[] = {
4485  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4486  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4487  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4488
4489 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4490 {
4491     BOOL ret;
4492     BYTE *buf = NULL;
4493     DWORD size = 0;
4494     CERT_ENHKEY_USAGE usage;
4495
4496     /* Test with empty usage */
4497     usage.cUsageIdentifier = 0;
4498     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4499      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4500     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4501     if (buf)
4502     {
4503         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4504         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4505         LocalFree(buf);
4506     }
4507     /* Test with a few usages */
4508     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4509     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4510     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4511      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4512     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4513     if (buf)
4514     {
4515         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4516         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4517         LocalFree(buf);
4518     }
4519 }
4520
4521 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4522 {
4523     BOOL ret;
4524     LPBYTE buf = NULL;
4525     DWORD size = 0;
4526
4527     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4528      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4529      (BYTE *)&buf, &size);
4530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4531     if (buf)
4532     {
4533         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4534
4535         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4536          "Wrong size %d\n", size);
4537         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4538          usage->cUsageIdentifier);
4539         LocalFree(buf);
4540     }
4541     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4542      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4543      (BYTE *)&buf, &size);
4544     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4545     if (buf)
4546     {
4547         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4548         DWORD i;
4549
4550         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4551          "Wrong size %d\n", size);
4552         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4553          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4554         for (i = 0; i < usage->cUsageIdentifier; i++)
4555             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4556              "Expected OID %s, got %s\n", keyUsages[i],
4557              usage->rgpszUsageIdentifier[i]);
4558         LocalFree(buf);
4559     }
4560 }
4561
4562 static BYTE keyId[] = { 1,2,3,4 };
4563 static const BYTE authorityKeyIdWithId[] = {
4564  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4565 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4566  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4567  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4568 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4569
4570 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4571 {
4572     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4573     BOOL ret;
4574     BYTE *buf = NULL;
4575     DWORD size = 0;
4576
4577     /* Test with empty id */
4578     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4579      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4580     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4581     if (buf)
4582     {
4583         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4584         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4585         LocalFree(buf);
4586     }
4587     /* With just a key id */
4588     info.KeyId.cbData = sizeof(keyId);
4589     info.KeyId.pbData = keyId;
4590     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4591      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4592     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4593     if (buf)
4594     {
4595         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4596         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4597         LocalFree(buf);
4598     }
4599     /* With just an issuer */
4600     info.KeyId.cbData = 0;
4601     info.CertIssuer.cbData = sizeof(encodedCommonName);
4602     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4603     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4604      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4605     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4606     if (buf)
4607     {
4608         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4609          size);
4610         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4611         LocalFree(buf);
4612     }
4613     /* With just a serial number */
4614     info.CertIssuer.cbData = 0;
4615     info.CertSerialNumber.cbData = sizeof(serialNum);
4616     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4617     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4618      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4619     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4620     if (buf)
4621     {
4622         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4623          size);
4624         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4625         LocalFree(buf);
4626     }
4627 }
4628
4629 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4630 {
4631     BOOL ret;
4632     LPBYTE buf = NULL;
4633     DWORD size = 0;
4634
4635     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4636      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4637      (BYTE *)&buf, &size);
4638     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4639     if (buf)
4640     {
4641         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4642
4643         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4644          size);
4645         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4646         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4647         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4648         LocalFree(buf);
4649     }
4650     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4651      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4652      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4653     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4654     if (buf)
4655     {
4656         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4657
4658         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4659          size);
4660         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4661         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4662          "Unexpected key id\n");
4663         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4664         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4665         LocalFree(buf);
4666     }
4667     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4668      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4669      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4670     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4671     if (buf)
4672     {
4673         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4674
4675         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4676          size);
4677         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4678         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4679          "Unexpected issuer len\n");
4680         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4681          sizeof(encodedCommonName)), "Unexpected issuer\n");
4682         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4683         LocalFree(buf);
4684     }
4685     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4686      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4687      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4688     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4689     if (buf)
4690     {
4691         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4692
4693         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4694          size);
4695         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4696         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4697         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4698          "Unexpected serial number len\n");
4699         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4700          "Unexpected serial number\n");
4701         LocalFree(buf);
4702     }
4703 }
4704
4705 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4706  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4707  0x6f,0x72,0x67 };
4708
4709 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4710 {
4711     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4712     CERT_ALT_NAME_ENTRY entry = { 0 };
4713     BOOL ret;
4714     BYTE *buf = NULL;
4715     DWORD size = 0;
4716
4717     /* Test with empty id */
4718     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4719      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4720     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4721     if (buf)
4722     {
4723         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4724         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4725         LocalFree(buf);
4726     }
4727     /* With just a key id */
4728     info.KeyId.cbData = sizeof(keyId);
4729     info.KeyId.pbData = keyId;
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(authorityKeyIdWithId), "Unexpected size %d\n",
4736          size);
4737         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4738         LocalFree(buf);
4739     }
4740     /* With a bogus issuer name */
4741     info.KeyId.cbData = 0;
4742     info.AuthorityCertIssuer.cAltEntry = 1;
4743     info.AuthorityCertIssuer.rgAltEntry = &entry;
4744     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4745      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4746     ok(!ret && GetLastError() == E_INVALIDARG,
4747      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4748     /* With an issuer name */
4749     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4750     U(entry).pwszURL = (LPWSTR)url;
4751     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4753     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4754     if (buf)
4755     {
4756         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4757          size);
4758         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4759          "Unexpected value\n");
4760         LocalFree(buf);
4761     }
4762     /* With just a serial number */
4763     info.AuthorityCertIssuer.cAltEntry = 0;
4764     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4765     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4766     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4767      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4768     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4769     if (buf)
4770     {
4771         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4772          size);
4773         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4774         LocalFree(buf);
4775     }
4776 }
4777
4778 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4779 {
4780     BOOL ret;
4781     LPBYTE buf = NULL;
4782     DWORD size = 0;
4783
4784     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4785      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4786      (BYTE *)&buf, &size);
4787     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4788     if (buf)
4789     {
4790         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4791
4792         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4793          size);
4794         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4795         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4796          "Expected no issuer name entries\n");
4797         ok(info->AuthorityCertSerialNumber.cbData == 0,
4798          "Expected no serial number\n");
4799         LocalFree(buf);
4800     }
4801     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4802      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4803      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4804     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4805     if (buf)
4806     {
4807         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4808
4809         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4810          size);
4811         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4812         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4813          "Unexpected key id\n");
4814         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4815          "Expected no issuer name entries\n");
4816         ok(info->AuthorityCertSerialNumber.cbData == 0,
4817          "Expected no serial number\n");
4818         LocalFree(buf);
4819     }
4820     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4821      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4822      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4823     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4824     if (buf)
4825     {
4826         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4827
4828         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4829          size);
4830         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4831         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4832          "Expected 1 issuer entry, got %d\n",
4833          info->AuthorityCertIssuer.cAltEntry);
4834         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4835          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4836          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4837         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4838          url), "Unexpected URL\n");
4839         ok(info->AuthorityCertSerialNumber.cbData == 0,
4840          "Expected no serial number\n");
4841         LocalFree(buf);
4842     }
4843     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4844      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4845      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4846     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4847     if (buf)
4848     {
4849         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4850
4851         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4852          size);
4853         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4854         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4855          "Expected no issuer name entries\n");
4856         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4857          "Unexpected serial number len\n");
4858         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4859          sizeof(serialNum)), "Unexpected serial number\n");
4860         LocalFree(buf);
4861     }
4862 }
4863
4864 static const BYTE authorityInfoAccessWithUrl[] = {
4865 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4866 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4867 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4868 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4869 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4870 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4871
4872 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4873 {
4874     static char oid1[] = "1.2.3";
4875     static char oid2[] = "1.5.6";
4876     BOOL ret;
4877     BYTE *buf = NULL;
4878     DWORD size = 0;
4879     CERT_ACCESS_DESCRIPTION accessDescription[2];
4880     CERT_AUTHORITY_INFO_ACCESS aia;
4881
4882     memset(accessDescription, 0, sizeof(accessDescription));
4883     aia.cAccDescr = 0;
4884     aia.rgAccDescr = NULL;
4885     /* Having no access descriptions is allowed */
4886     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4887      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4888     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4889     if (buf)
4890     {
4891         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4892         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4893         LocalFree(buf);
4894         buf = NULL;
4895     }
4896     /* It can't have an empty access method */
4897     aia.cAccDescr = 1;
4898     aia.rgAccDescr = accessDescription;
4899     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4900      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4901     ok(!ret && (GetLastError() == E_INVALIDARG ||
4902      GetLastError() == OSS_LIMITED /* Win9x */),
4903      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4904     /* It can't have an empty location */
4905     accessDescription[0].pszAccessMethod = oid1;
4906     SetLastError(0xdeadbeef);
4907     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4908      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4909     ok(!ret && GetLastError() == E_INVALIDARG,
4910      "expected E_INVALIDARG, got %08x\n", GetLastError());
4911     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4912     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4913     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4914      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4915     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4916     if (buf)
4917     {
4918         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4919          size);
4920         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4921          "unexpected value\n");
4922         LocalFree(buf);
4923         buf = NULL;
4924     }
4925     accessDescription[1].pszAccessMethod = oid2;
4926     accessDescription[1].AccessLocation.dwAltNameChoice =
4927      CERT_ALT_NAME_IP_ADDRESS;
4928     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4929      sizeof(encodedIPAddr);
4930     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4931      (LPBYTE)encodedIPAddr;
4932     aia.cAccDescr = 2;
4933     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4934      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4935     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4936     if (buf)
4937     {
4938         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4939          "unexpected size %d\n", size);
4940         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4941          "unexpected value\n");
4942         LocalFree(buf);
4943         buf = NULL;
4944     }
4945 }
4946
4947 static void compareAuthorityInfoAccess(LPCSTR header,
4948  const CERT_AUTHORITY_INFO_ACCESS *expected,
4949  const CERT_AUTHORITY_INFO_ACCESS *got)
4950 {
4951     DWORD i;
4952
4953     ok(expected->cAccDescr == got->cAccDescr,
4954      "%s: expected %d access descriptions, got %d\n", header,
4955      expected->cAccDescr, got->cAccDescr);
4956     for (i = 0; i < expected->cAccDescr; i++)
4957     {
4958         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4959          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4960          header, i, expected->rgAccDescr[i].pszAccessMethod,
4961          got->rgAccDescr[i].pszAccessMethod);
4962         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4963          &got->rgAccDescr[i].AccessLocation);
4964     }
4965 }
4966
4967 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4968 {
4969     static char oid1[] = "1.2.3";
4970     static char oid2[] = "1.5.6";
4971     BOOL ret;
4972     LPBYTE buf = NULL;
4973     DWORD size = 0;
4974
4975     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4976      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4977      (BYTE *)&buf, &size);
4978     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4979     if (buf)
4980     {
4981         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4982
4983         compareAuthorityInfoAccess("empty AIA", &aia,
4984          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4985         LocalFree(buf);
4986         buf = NULL;
4987     }
4988     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4989      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4990      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4991     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4992     if (buf)
4993     {
4994         CERT_ACCESS_DESCRIPTION accessDescription;
4995         CERT_AUTHORITY_INFO_ACCESS aia;
4996
4997         accessDescription.pszAccessMethod = oid1;
4998         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4999         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5000         aia.cAccDescr = 1;
5001         aia.rgAccDescr = &accessDescription;
5002         compareAuthorityInfoAccess("AIA with URL", &aia,
5003          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5004         LocalFree(buf);
5005         buf = NULL;
5006     }
5007     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5008      authorityInfoAccessWithUrlAndIPAddr,
5009      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5010      NULL, (BYTE *)&buf, &size);
5011     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5012     if (buf)
5013     {
5014         CERT_ACCESS_DESCRIPTION accessDescription[2];
5015         CERT_AUTHORITY_INFO_ACCESS aia;
5016
5017         accessDescription[0].pszAccessMethod = oid1;
5018         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5019         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5020         accessDescription[1].pszAccessMethod = oid2;
5021         accessDescription[1].AccessLocation.dwAltNameChoice =
5022          CERT_ALT_NAME_IP_ADDRESS;
5023         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5024          sizeof(encodedIPAddr);
5025         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5026          (LPBYTE)encodedIPAddr;
5027         aia.cAccDescr = 2;
5028         aia.rgAccDescr = accessDescription;
5029         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5030          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5031         LocalFree(buf);
5032         buf = NULL;
5033     }
5034 }
5035
5036 static const BYTE emptyCTL[] = {
5037 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5038 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5039 static const BYTE emptyCTLWithVersion1[] = {
5040 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5041 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5042 static const BYTE ctlWithUsageIdentifier[] = {
5043 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5044 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5045 static const BYTE ctlWithListIdentifier[] = {
5046 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5047 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5048 static const BYTE ctlWithSequenceNumber[] = {
5049 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5050 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5051 static const BYTE ctlWithThisUpdate[] = {
5052 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5053 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5054 static const BYTE ctlWithThisAndNextUpdate[] = {
5055 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5056 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5057 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5058 static const BYTE ctlWithAlgId[] = {
5059 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5060 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5061 static const BYTE ctlWithBogusEntry[] = {
5062 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5063 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5064 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5065 static const BYTE ctlWithOneEntry[] = {
5066 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5067 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5068 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5069 static const BYTE ctlWithTwoEntries[] = {
5070 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5071 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5072 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5073 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5074 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5075
5076 static void test_encodeCTL(DWORD dwEncoding)
5077 {
5078     static char oid1[] = "1.2.3";
5079     static char oid2[] = "1.5.6";
5080     char *pOid1 = oid1;
5081     BOOL ret;
5082     BYTE *buf = NULL;
5083     DWORD size = 0;
5084     CTL_INFO info;
5085     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5086     CTL_ENTRY ctlEntry[2];
5087     CRYPT_ATTRIBUTE attr1, attr2;
5088     CRYPT_ATTR_BLOB value1, value2;
5089
5090     memset(&info, 0, sizeof(info));
5091     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5092      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5093     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5094     if (buf)
5095     {
5096         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5097         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5098         LocalFree(buf);
5099         buf = NULL;
5100     }
5101     info.dwVersion = 1;
5102     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5103      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5104     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5105     if (buf)
5106     {
5107         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5108         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5109         LocalFree(buf);
5110         buf = NULL;
5111     }
5112     info.dwVersion = 0;
5113     info.SubjectUsage.cUsageIdentifier = 1;
5114     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5115     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5116      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5117     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5118     if (buf)
5119     {
5120         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5121          size);
5122         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5123         LocalFree(buf);
5124         buf = NULL;
5125     }
5126     info.SubjectUsage.cUsageIdentifier = 0;
5127     info.ListIdentifier.cbData = sizeof(serialNum);
5128     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5129     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5130      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5131     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5132     if (buf)
5133     {
5134         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5135         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5136         LocalFree(buf);
5137         buf = NULL;
5138     }
5139     info.ListIdentifier.cbData = 0;
5140     info.SequenceNumber.cbData = sizeof(serialNum);
5141     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5142     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5143      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5144     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5145     if (buf)
5146     {
5147         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5148          size);
5149         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5150         LocalFree(buf);
5151         buf = NULL;
5152     }
5153     info.SequenceNumber.cbData = 0;
5154     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5155     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5156      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5157     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5158     if (buf)
5159     {
5160         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5161         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5162         LocalFree(buf);
5163         buf = NULL;
5164     }
5165     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5166     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5167      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5168     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5169     if (buf)
5170     {
5171         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5172          size);
5173         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5174         LocalFree(buf);
5175         buf = NULL;
5176     }
5177     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5178     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5179     info.SubjectAlgorithm.pszObjId = oid2;
5180     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5181      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5182     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5183     if (buf)
5184     {
5185         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5186         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5187         LocalFree(buf);
5188         buf = NULL;
5189     }
5190     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5191      * (see tests below) but it'll encode fine.
5192      */
5193     info.SubjectAlgorithm.pszObjId = NULL;
5194     value1.cbData = sizeof(serialNum);
5195     value1.pbData = (LPBYTE)serialNum;
5196     attr1.pszObjId = oid1;
5197     attr1.cValue = 1;
5198     attr1.rgValue = &value1;
5199     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5200     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5201     ctlEntry[0].cAttribute = 1;
5202     ctlEntry[0].rgAttribute = &attr1;
5203     info.cCTLEntry = 1;
5204     info.rgCTLEntry = ctlEntry;
5205     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5206      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5207     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5208     if (buf)
5209     {
5210         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5211         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5212         LocalFree(buf);
5213         buf = NULL;
5214     }
5215     value1.cbData = sizeof(emptySequence);
5216     value1.pbData = (LPBYTE)emptySequence;
5217     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5218      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5219     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5220     if (buf)
5221     {
5222         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5223         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5224         LocalFree(buf);
5225         buf = NULL;
5226     }
5227     value2.cbData = sizeof(encodedIPAddr);
5228     value2.pbData = (LPBYTE)encodedIPAddr;
5229     attr2.pszObjId = oid2;
5230     attr2.cValue = 1;
5231     attr2.rgValue = &value2;
5232     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5233     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5234     ctlEntry[1].cAttribute = 1;
5235     ctlEntry[1].rgAttribute = &attr2;
5236     info.cCTLEntry = 2;
5237     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5238      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5239     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5240     if (buf)
5241     {
5242         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5243         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5244         LocalFree(buf);
5245         buf = NULL;
5246     }
5247 }
5248
5249 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5250  const CTL_INFO *got)
5251 {
5252     DWORD i, j, k;
5253
5254     ok(expected->dwVersion == got->dwVersion,
5255      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5256      got->dwVersion);
5257     ok(expected->SubjectUsage.cUsageIdentifier ==
5258      got->SubjectUsage.cUsageIdentifier,
5259      "%s: expected %d usage identifiers, got %d\n", header,
5260      expected->SubjectUsage.cUsageIdentifier,
5261      got->SubjectUsage.cUsageIdentifier);
5262     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5263         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5264          got->SubjectUsage.rgpszUsageIdentifier[i]),
5265          "%s[%d]: expected %s, got %s\n", header, i,
5266          expected->SubjectUsage.rgpszUsageIdentifier[i],
5267          got->SubjectUsage.rgpszUsageIdentifier[i]);
5268     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5269      "%s: expected list identifier of %d bytes, got %d\n", header,
5270      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5271     if (expected->ListIdentifier.cbData)
5272         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5273          expected->ListIdentifier.cbData),
5274          "%s: unexpected list identifier value\n", header);
5275     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5276      "%s: expected sequence number of %d bytes, got %d\n", header,
5277      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5278     if (expected->SequenceNumber.cbData)
5279         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5280          expected->SequenceNumber.cbData),
5281          "%s: unexpected sequence number value\n", header);
5282     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5283      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5284      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5285      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5286     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5287      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5288      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5289      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5290     if (expected->SubjectAlgorithm.pszObjId &&
5291      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5292         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5293          expected->SubjectAlgorithm.pszObjId);
5294     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5295         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5296          got->SubjectAlgorithm.pszObjId),
5297          "%s: expected subject algorithm %s, got %s\n", header,
5298          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5299     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5300      got->SubjectAlgorithm.Parameters.cbData,
5301      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5302      expected->SubjectAlgorithm.Parameters.cbData,
5303      got->SubjectAlgorithm.Parameters.cbData);
5304     if (expected->SubjectAlgorithm.Parameters.cbData)
5305         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5306          got->SubjectAlgorithm.Parameters.pbData,
5307          expected->SubjectAlgorithm.Parameters.cbData),
5308          "%s: unexpected subject algorithm parameter value\n", header);
5309     ok(expected->cCTLEntry == got->cCTLEntry,
5310      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5311      got->cCTLEntry);
5312     for (i = 0; i < expected->cCTLEntry; i++)
5313     {
5314         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5315          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5316          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5317          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5318          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5319         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5320             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5321              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5322              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5323              "%s[%d]: unexpected subject identifier value\n",
5324              header, i);
5325         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5326         {
5327             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5328              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5329              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5330              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5331              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5332             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5333             {
5334                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5335                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5336                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5337                  header, i, j, k,
5338                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5339                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5340                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5341                     ok(!memcmp(
5342                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5343                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5344                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5345                      "%s[%d][%d][%d]: unexpected value\n",
5346                      header, i, j, k);
5347             }
5348         }
5349     }
5350     ok(expected->cExtension == got->cExtension,
5351      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5352      got->cExtension);
5353     for (i = 0; i < expected->cExtension; i++)
5354     {
5355         ok(!strcmp(expected->rgExtension[i].pszObjId,
5356          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5357          header, i, expected->rgExtension[i].pszObjId,
5358          got->rgExtension[i].pszObjId);
5359         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5360          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5361          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5362         ok(expected->rgExtension[i].Value.cbData ==
5363          got->rgExtension[i].Value.cbData,
5364          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5365          header, i, expected->rgExtension[i].Value.cbData,
5366          got->rgExtension[i].Value.cbData);
5367         if (expected->rgExtension[i].Value.cbData)
5368             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5369              got->rgExtension[i].Value.pbData,
5370              expected->rgExtension[i].Value.cbData),
5371              "%s[%d]: unexpected extension value\n", header, i);
5372     }
5373 }
5374
5375 static const BYTE signedCTL[] = {
5376 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5377 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5378 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5379 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5380 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5381 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5382 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5383 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5384 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5385 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5386 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5387 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5388 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5389 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5390 static const BYTE signedCTLWithCTLInnerContent[] = {
5391 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5392 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5393 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5394 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5395 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5396 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5397 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5398 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5399 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5400 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5401 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5402 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5403 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5404 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5405 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5406 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5407 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5408 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5409 0x57,0x6c,0x0b,0x47,0xb8 };
5410
5411 static void test_decodeCTL(DWORD dwEncoding)
5412 {
5413     static char oid1[] = "1.2.3";
5414     static char oid2[] = "1.5.6";
5415     static BYTE nullData[] = { 5,0 };
5416     char *pOid1 = oid1;
5417     BOOL ret;
5418     BYTE *buf = NULL;
5419     DWORD size = 0;
5420     CTL_INFO info;
5421     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5422     CTL_ENTRY ctlEntry[2];
5423     CRYPT_ATTRIBUTE attr1, attr2;
5424     CRYPT_ATTR_BLOB value1, value2;
5425
5426     memset(&info, 0, sizeof(info));
5427     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5428      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5429     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5430     if (buf)
5431     {
5432         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5433         LocalFree(buf);
5434         buf = NULL;
5435     }
5436     info.dwVersion = 1;
5437     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5438      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5439      &size);
5440     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5441     if (buf)
5442     {
5443         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5444         LocalFree(buf);
5445         buf = NULL;
5446     }
5447     info.dwVersion = 0;
5448     info.SubjectUsage.cUsageIdentifier = 1;
5449     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5450     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5451      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5452      (BYTE *)&buf, &size);
5453     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5454     if (buf)
5455     {
5456         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5457         LocalFree(buf);
5458         buf = NULL;
5459     }
5460     info.SubjectUsage.cUsageIdentifier = 0;
5461     info.ListIdentifier.cbData = sizeof(serialNum);
5462     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5463     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5464      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5465      (BYTE *)&buf, &size);
5466     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5467     if (buf)
5468     {
5469         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5470         LocalFree(buf);
5471         buf = NULL;
5472     }
5473     info.ListIdentifier.cbData = 0;
5474     info.SequenceNumber.cbData = sizeof(serialNum);
5475     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5476     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5477      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5478      (BYTE *)&buf, &size);
5479     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5480     if (buf)
5481     {
5482         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5483         LocalFree(buf);
5484         buf = NULL;
5485     }
5486     info.SequenceNumber.cbData = 0;
5487     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5488     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5489      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5490      (BYTE *)&buf, &size);
5491     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5492     if (buf)
5493     {
5494         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5495         LocalFree(buf);
5496         buf = NULL;
5497     }
5498     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5499     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5500      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5501      (BYTE *)&buf, &size);
5502     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5503     if (buf)
5504     {
5505         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5506         LocalFree(buf);
5507         buf = NULL;
5508     }
5509     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5510     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5511     info.SubjectAlgorithm.pszObjId = oid2;
5512     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5513     info.SubjectAlgorithm.Parameters.pbData = nullData;
5514     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5515      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5516      (BYTE *)&buf, &size);
5517     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5518     if (buf)
5519     {
5520         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5521         LocalFree(buf);
5522         buf = NULL;
5523     }
5524     SetLastError(0xdeadbeef);
5525     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5526      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5527      (BYTE *)&buf, &size);
5528     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5529      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5530      GetLastError());
5531     info.SubjectAlgorithm.Parameters.cbData = 0;
5532     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5533     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5534     info.SubjectAlgorithm.pszObjId = oid2;
5535     info.SubjectAlgorithm.pszObjId = NULL;
5536     value1.cbData = sizeof(emptySequence);
5537     value1.pbData = (LPBYTE)emptySequence;
5538     attr1.pszObjId = oid1;
5539     attr1.cValue = 1;
5540     attr1.rgValue = &value1;
5541     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5542     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5543     ctlEntry[0].cAttribute = 1;
5544     ctlEntry[0].rgAttribute = &attr1;
5545     info.cCTLEntry = 1;
5546     info.rgCTLEntry = ctlEntry;
5547     SetLastError(0xdeadbeef);
5548     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5549      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5550      (BYTE *)&buf, &size);
5551     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5552     if (buf)
5553     {
5554         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5555         LocalFree(buf);
5556         buf = NULL;
5557     }
5558     value2.cbData = sizeof(encodedIPAddr);
5559     value2.pbData = (LPBYTE)encodedIPAddr;
5560     attr2.pszObjId = oid2;
5561     attr2.cValue = 1;
5562     attr2.rgValue = &value2;
5563     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5564     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5565     ctlEntry[1].cAttribute = 1;
5566     ctlEntry[1].rgAttribute = &attr2;
5567     info.cCTLEntry = 2;
5568     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5569      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5570      (BYTE *)&buf, &size);
5571     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5572     if (buf)
5573     {
5574         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5575         LocalFree(buf);
5576         buf = NULL;
5577     }
5578     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5579     SetLastError(0xdeadbeef);
5580     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5581      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5582     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5583      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5584      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5585      GetLastError());
5586     SetLastError(0xdeadbeef);
5587     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5588      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5589      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5590     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5591      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5592      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5593      GetLastError());
5594 }
5595
5596 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5597 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5598  0x03,0,0,0,0,0,0 };
5599 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5600  0xa0,0x01,0x01 };
5601 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5602  0x03,0x02,0x01,0x01 };
5603 static BYTE bogusDER[] = { 1 };
5604
5605 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5606 {
5607     BOOL ret;
5608     BYTE *buf = NULL;
5609     DWORD size = 0;
5610     CRYPT_CONTENT_INFO info = { 0 };
5611     char oid1[] = "1.2.3";
5612
5613     if (0)
5614     {
5615         /* Crashes on win9x */
5616         SetLastError(0xdeadbeef);
5617         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5618          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5619         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5620          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5621     }
5622     SetLastError(0xdeadbeef);
5623     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5624      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5625     ok(!ret && (GetLastError() == E_INVALIDARG ||
5626      GetLastError() == OSS_LIMITED /* Win9x */),
5627      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5628     info.pszObjId = oid1;
5629     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5630      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5631     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5632     if (buf)
5633     {
5634         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5635         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5636         LocalFree(buf);
5637     }
5638     info.Content.pbData = bogusDER;
5639     info.Content.cbData = sizeof(bogusDER);
5640     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5641      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5642     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5643     if (buf)
5644     {
5645         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5646         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5647         LocalFree(buf);
5648     }
5649     info.Content.pbData = (BYTE *)ints[0].encoded;
5650     info.Content.cbData = ints[0].encoded[1] + 2;
5651     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5652      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5653     if (buf)
5654     {
5655         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5656         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5657         LocalFree(buf);
5658     }
5659 }
5660
5661 static const BYTE indefiniteSignedPKCSContent[] = {
5662 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5663 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5664 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5665 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5666 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5667 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5668 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5669 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5670 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5671 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5672 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5673 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5674 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5675 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5676 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5677 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5678 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5679 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5680 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5681 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5682 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5683 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5684 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5685 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5686 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5687 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5688 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5689 0x00,0x00,0x00,0x00,0x00,0x00 };
5690
5691 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5692 {
5693     BOOL ret;
5694     LPBYTE buf = NULL;
5695     DWORD size = 0;
5696     CRYPT_CONTENT_INFO *info;
5697
5698     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5699      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5700      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5701     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5702     if (buf)
5703     {
5704         info = (CRYPT_CONTENT_INFO *)buf;
5705
5706         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5707          info->pszObjId);
5708         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5709          info->Content.cbData);
5710         LocalFree(buf);
5711     }
5712     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5713      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5714      0, NULL, NULL, &size);
5715     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5716     SetLastError(0xdeadbeef);
5717     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5718      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5719      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5720     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5721      * I doubt an app depends on that.
5722      */
5723     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5724      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5725      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5726      GetLastError());
5727     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5728      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5729      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5730     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5731     if (buf)
5732     {
5733         info = (CRYPT_CONTENT_INFO *)buf;
5734
5735         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5736          info->pszObjId);
5737         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5738          "Unexpected size %d\n", info->Content.cbData);
5739         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5740          info->Content.cbData), "Unexpected value\n");
5741         LocalFree(buf);
5742     }
5743     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5744      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5745      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5746     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5747     if (buf)
5748     {
5749         info = (CRYPT_CONTENT_INFO *)buf;
5750
5751         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5752          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5753         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5754          info->Content.cbData);
5755         LocalFree(buf);
5756     }
5757 }
5758
5759 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5760  0x00 };
5761 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5762  0x01 };
5763 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5764  0x02,0x01,0x01 };
5765
5766 static void test_encodePKCSAttribute(DWORD dwEncoding)
5767 {
5768     CRYPT_ATTRIBUTE attr = { 0 };
5769     BOOL ret;
5770     LPBYTE buf = NULL;
5771     DWORD size = 0;
5772     CRYPT_ATTR_BLOB blob;
5773     char oid[] = "1.2.3";
5774
5775     if (0)
5776     {
5777         /* Crashes on win9x */
5778         SetLastError(0xdeadbeef);
5779         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5780          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5781         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5782          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5783     }
5784     SetLastError(0xdeadbeef);
5785     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5786      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5787     ok(!ret && (GetLastError() == E_INVALIDARG ||
5788      GetLastError() == OSS_LIMITED /* Win9x */),
5789      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5790     attr.pszObjId = oid;
5791     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5792      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5793     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5794     if (buf)
5795     {
5796         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5797         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5798         LocalFree(buf);
5799     }
5800     blob.cbData = sizeof(bogusDER);
5801     blob.pbData = bogusDER;
5802     attr.cValue = 1;
5803     attr.rgValue = &blob;
5804     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5805      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5806     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5807     if (buf)
5808     {
5809         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5810         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5811         LocalFree(buf);
5812     }
5813     blob.pbData = (BYTE *)ints[0].encoded;
5814     blob.cbData = ints[0].encoded[1] + 2;
5815     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5816      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5817     if (buf)
5818     {
5819         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5820         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5821         LocalFree(buf);
5822     }
5823 }
5824
5825 static void test_decodePKCSAttribute(DWORD dwEncoding)
5826 {
5827     BOOL ret;
5828     LPBYTE buf = NULL;
5829     DWORD size = 0;
5830     CRYPT_ATTRIBUTE *attr;
5831
5832     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5833      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5834      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5835     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5836     if (buf)
5837     {
5838         attr = (CRYPT_ATTRIBUTE *)buf;
5839
5840         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5841          attr->pszObjId);
5842         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5843         LocalFree(buf);
5844     }
5845     SetLastError(0xdeadbeef);
5846     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5847      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5848      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5849     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5850      * I doubt an app depends on that.
5851      */
5852     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5853      GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */),
5854      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5855      GetLastError());
5856     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5857      intPKCSAttr, sizeof(intPKCSAttr),
5858      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5859     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5860     if (buf)
5861     {
5862         attr = (CRYPT_ATTRIBUTE *)buf;
5863
5864         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5865          attr->pszObjId);
5866         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5867         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5868          "Unexpected size %d\n", attr->rgValue[0].cbData);
5869         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5870          attr->rgValue[0].cbData), "Unexpected value\n");
5871         LocalFree(buf);
5872     }
5873 }
5874
5875 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5876 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5877  0x2a,0x03,0x31,0x00 };
5878 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5879  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5880
5881 static void test_encodePKCSAttributes(DWORD dwEncoding)
5882 {
5883     CRYPT_ATTRIBUTES attributes = { 0 };
5884     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5885     CRYPT_ATTR_BLOB blob;
5886     BOOL ret;
5887     LPBYTE buf = NULL;
5888     DWORD size = 0;
5889     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5890
5891     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5892      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5893     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5894     if (buf)
5895     {
5896         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5897         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5898         LocalFree(buf);
5899     }
5900     attributes.cAttr = 1;
5901     attributes.rgAttr = attr;
5902     SetLastError(0xdeadbeef);
5903     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5904      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5905     ok(!ret && (GetLastError() == E_INVALIDARG ||
5906      GetLastError() == OSS_LIMITED /* Win9x */),
5907      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5908     attr[0].pszObjId = oid1;
5909     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5910      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5911     if (buf)
5912     {
5913         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5914         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5915         LocalFree(buf);
5916     }
5917     attr[1].pszObjId = oid2;
5918     attr[1].cValue = 1;
5919     attr[1].rgValue = &blob;
5920     blob.pbData = (BYTE *)ints[0].encoded;
5921     blob.cbData = ints[0].encoded[1] + 2;
5922     attributes.cAttr = 2;
5923     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5924      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5925     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5926     if (buf)
5927     {
5928         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5929         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5930         LocalFree(buf);
5931     }
5932 }
5933
5934 static void test_decodePKCSAttributes(DWORD dwEncoding)
5935 {
5936     BOOL ret;
5937     LPBYTE buf = NULL;
5938     DWORD size = 0;
5939     CRYPT_ATTRIBUTES *attributes;
5940
5941     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5942      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5943      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5944     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5945     if (buf)
5946     {
5947         attributes = (CRYPT_ATTRIBUTES *)buf;
5948         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5949          attributes->cAttr);
5950         LocalFree(buf);
5951     }
5952     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5953      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5954      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5955     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5956     if (buf)
5957     {
5958         attributes = (CRYPT_ATTRIBUTES *)buf;
5959         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5960          attributes->cAttr);
5961         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5962          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5963         ok(attributes->rgAttr[0].cValue == 0,
5964          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5965         LocalFree(buf);
5966     }
5967     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5968      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5969      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5970     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5971     if (buf)
5972     {
5973         attributes = (CRYPT_ATTRIBUTES *)buf;
5974         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5975          attributes->cAttr);
5976         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5977          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5978         ok(attributes->rgAttr[0].cValue == 0,
5979          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5980         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5981          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5982         ok(attributes->rgAttr[1].cValue == 1,
5983          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5984         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5985          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5986         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5987          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5988         LocalFree(buf);
5989     }
5990 }
5991
5992 static const BYTE singleCapability[] = {
5993 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5994 static const BYTE twoCapabilities[] = {
5995 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5996 static const BYTE singleCapabilitywithNULL[] = {
5997 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5998
5999 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6000 {
6001     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6002     BOOL ret;
6003     LPBYTE buf = NULL;
6004     DWORD size = 0;
6005     CRYPT_SMIME_CAPABILITY capability[2];
6006     CRYPT_SMIME_CAPABILITIES capabilities;
6007
6008     /* An empty capabilities is allowed */
6009     capabilities.cCapability = 0;
6010     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6011      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6012     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6013     if (buf)
6014     {
6015         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6016         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6017         LocalFree(buf);
6018     }
6019     /* A non-empty capabilities with an empty capability (lacking an OID) is
6020      * not allowed
6021      */
6022     capability[0].pszObjId = NULL;
6023     capability[0].Parameters.cbData = 0;
6024     capabilities.cCapability = 1;
6025     capabilities.rgCapability = capability;
6026     SetLastError(0xdeadbeef);
6027     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6028      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6029     ok(!ret && (GetLastError() == E_INVALIDARG ||
6030      GetLastError() == OSS_LIMITED /* Win9x */),
6031      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6032     capability[0].pszObjId = oid1;
6033     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6034      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6035     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6036     if (buf)
6037     {
6038         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6039         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6040         LocalFree(buf);
6041     }
6042     capability[1].pszObjId = oid2;
6043     capability[1].Parameters.cbData = 0;
6044     capabilities.cCapability = 2;
6045     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6046      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6047     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6048     if (buf)
6049     {
6050         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6051         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6052         LocalFree(buf);
6053     }
6054 }
6055
6056 static void compareSMimeCapabilities(LPCSTR header,
6057  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6058 {
6059     DWORD i;
6060
6061     ok(got->cCapability == expected->cCapability,
6062      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6063      got->cCapability);
6064     for (i = 0; i < expected->cCapability; i++)
6065     {
6066         ok(!strcmp(expected->rgCapability[i].pszObjId,
6067          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6068          header, i, expected->rgCapability[i].pszObjId,
6069          got->rgCapability[i].pszObjId);
6070         ok(expected->rgCapability[i].Parameters.cbData ==
6071          got->rgCapability[i].Parameters.cbData,
6072          "%s[%d]: expected %d bytes, got %d\n", header, i,
6073          expected->rgCapability[i].Parameters.cbData,
6074          got->rgCapability[i].Parameters.cbData);
6075         if (expected->rgCapability[i].Parameters.cbData)
6076             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6077              got->rgCapability[i].Parameters.pbData,
6078              expected->rgCapability[i].Parameters.cbData),
6079              "%s[%d]: unexpected value\n", header, i);
6080     }
6081 }
6082
6083 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6084 {
6085     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6086     BOOL ret;
6087     DWORD size = 0;
6088     CRYPT_SMIME_CAPABILITY capability[2];
6089     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6090
6091     SetLastError(0xdeadbeef);
6092     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6093      emptySequence, sizeof(emptySequence),
6094      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6095     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6096     if (ret)
6097     {
6098         capabilities.cCapability = 0;
6099         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6100         LocalFree(ptr);
6101     }
6102     SetLastError(0xdeadbeef);
6103     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6104      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6105      (BYTE *)&ptr, &size);
6106     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6107     if (ret)
6108     {
6109         capability[0].pszObjId = oid1;
6110         capability[0].Parameters.cbData = 0;
6111         capabilities.cCapability = 1;
6112         capabilities.rgCapability = capability;
6113         compareSMimeCapabilities("single capability", &capabilities, ptr);
6114         LocalFree(ptr);
6115     }
6116     SetLastError(0xdeadbeef);
6117     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6118      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6119      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6120     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6121     if (ret)
6122     {
6123         BYTE NULLparam[] = {0x05, 0x00};
6124         capability[0].pszObjId = oid1;
6125         capability[0].Parameters.cbData = 2;
6126         capability[0].Parameters.pbData = NULLparam;
6127         capabilities.cCapability = 1;
6128         capabilities.rgCapability = capability;
6129         compareSMimeCapabilities("single capability with NULL", &capabilities,
6130          ptr);
6131         LocalFree(ptr);
6132     }
6133     SetLastError(0xdeadbeef);
6134     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6135     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6136     (BYTE *)&ptr, &size);
6137     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6138     if (ret)
6139     {
6140         capability[0].Parameters.cbData = 0;
6141         capability[1].pszObjId = oid2;
6142         capability[1].Parameters.cbData = 0;
6143         capabilities.cCapability = 2;
6144         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6145         LocalFree(ptr);
6146     }
6147 }
6148
6149 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6150  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6151  0x67 };
6152 static const BYTE minimalPKCSSigner[] = {
6153  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6154  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6155  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6156 static const BYTE PKCSSignerWithSerial[] = {
6157  0x30,0x2c,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,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6160  0x00 };
6161 static const BYTE PKCSSignerWithHashAlgo[] = {
6162  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6163  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6164  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6165  0x00,0x04,0x00 };
6166 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6167  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6168  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6169  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6170  0x06,0x05,0x00,0x04,0x00 };
6171 static const BYTE PKCSSignerWithHash[] = {
6172  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6173  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6174  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6175  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6176  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6177 static const BYTE PKCSSignerWithAuthAttr[] = {
6178 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6179 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6180 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6181 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6182 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6183 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6184 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6185
6186 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6187 {
6188     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6189     BOOL ret;
6190     LPBYTE buf = NULL;
6191     DWORD size = 0;
6192     CMSG_SIGNER_INFO info = { 0 };
6193     char oid_common_name[] = szOID_COMMON_NAME;
6194     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6195      (LPBYTE)encodedCommonName };
6196     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6197
6198     SetLastError(0xdeadbeef);
6199     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6200      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6201     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6202     {
6203         skip("no PKCS7_SIGNER_INFO encode support\n");
6204         return;
6205     }
6206     ok(!ret && (GetLastError() == E_INVALIDARG ||
6207      GetLastError() == OSS_LIMITED /* Win9x */),
6208      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6209     /* To be encoded, a signer must have an issuer at least, and the encoding
6210      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6211      * see decoding tests.)
6212      */
6213     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6214     info.Issuer.pbData = encodedCommonNameNoNull;
6215     SetLastError(0xdeadbeef);
6216     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6217      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6218     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6219         ok(!ret && GetLastError() == E_INVALIDARG,
6220          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6221     else
6222     {
6223         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6224          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6225         if (buf)
6226         {
6227             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6228             if (size == sizeof(minimalPKCSSigner))
6229                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6230             else
6231                 ok(0, "Unexpected value\n");
6232             LocalFree(buf);
6233         }
6234     }
6235     info.SerialNumber.cbData = sizeof(serialNum);
6236     info.SerialNumber.pbData = (BYTE *)serialNum;
6237     SetLastError(0xdeadbeef);
6238     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6239      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6240     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6241         ok(!ret && GetLastError() == E_INVALIDARG,
6242          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6243     else
6244     {
6245         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6246          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6247         if (buf)
6248         {
6249             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6250              size);
6251             if (size == sizeof(PKCSSignerWithSerial))
6252                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6253                  "Unexpected value\n");
6254             else
6255                 ok(0, "Unexpected value\n");
6256             LocalFree(buf);
6257         }
6258     }
6259     info.HashAlgorithm.pszObjId = oid1;
6260     SetLastError(0xdeadbeef);
6261     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6262      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6263     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6264         ok(!ret && GetLastError() == E_INVALIDARG,
6265          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6266     else
6267     {
6268         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6269          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6270         if (buf)
6271         {
6272             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6273              size);
6274             if (size == sizeof(PKCSSignerWithHashAlgo))
6275                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6276                  "Unexpected value\n");
6277             else
6278                 ok(0, "Unexpected value\n");
6279             LocalFree(buf);
6280         }
6281     }
6282     info.HashEncryptionAlgorithm.pszObjId = oid2;
6283     SetLastError(0xdeadbeef);
6284     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6285      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6286     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6287         ok(!ret && GetLastError() == E_INVALIDARG,
6288          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6289     else
6290     {
6291         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6292         if (buf)
6293         {
6294             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6295              "Unexpected size %d\n", size);
6296             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6297                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6298                  "Unexpected value\n");
6299             else
6300                 ok(0, "Unexpected value\n");
6301             LocalFree(buf);
6302         }
6303     }
6304     info.EncryptedHash.cbData = sizeof(hash);
6305     info.EncryptedHash.pbData = (BYTE *)hash;
6306     SetLastError(0xdeadbeef);
6307     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6308      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6309     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6310         ok(!ret && GetLastError() == E_INVALIDARG,
6311          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6312     else
6313     {
6314         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6315         if (buf)
6316         {
6317             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6318              size);
6319             if (size == sizeof(PKCSSignerWithHash))
6320                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6321                  "Unexpected value\n");
6322             else
6323                 ok(0, "Unexpected value\n");
6324             LocalFree(buf);
6325         }
6326     }
6327     info.AuthAttrs.cAttr = 1;
6328     info.AuthAttrs.rgAttr = &attr;
6329     SetLastError(0xdeadbeef);
6330     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6331      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6332     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6333         ok(!ret && GetLastError() == E_INVALIDARG,
6334          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6335     else
6336     {
6337         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6338         if (buf)
6339         {
6340             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6341              size);
6342             if (size == sizeof(PKCSSignerWithAuthAttr))
6343                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6344                  "Unexpected value\n");
6345             else
6346                 ok(0, "Unexpected value\n");
6347             LocalFree(buf);
6348         }
6349     }
6350 }
6351
6352 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6353 {
6354     BOOL ret;
6355     LPBYTE buf = NULL;
6356     DWORD size = 0;
6357     CMSG_SIGNER_INFO *info;
6358
6359     /* A PKCS signer can't be decoded without a serial number. */
6360     SetLastError(0xdeadbeef);
6361     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6362      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6363      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6364     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6365      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6366      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6367      GetLastError());
6368     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6369      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6370      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6371     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6372      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6373     if (buf)
6374     {
6375         info = (CMSG_SIGNER_INFO *)buf;
6376         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6377          info->dwVersion);
6378         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6379          "Unexpected size %d\n", info->Issuer.cbData);
6380         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6381          info->Issuer.cbData), "Unexpected value\n");
6382         ok(info->SerialNumber.cbData == sizeof(serialNum),
6383          "Unexpected size %d\n", info->SerialNumber.cbData);
6384         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6385          "Unexpected value\n");
6386         LocalFree(buf);
6387     }
6388     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6389      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6390      CRYPT_DECODE_ALLOC_FLAG, 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         LocalFree(buf);
6407     }
6408     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6409      PKCSSignerWithHashAndEncryptionAlgo,
6410      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6411      NULL, (BYTE *)&buf, &size);
6412     if (buf)
6413     {
6414         info = (CMSG_SIGNER_INFO *)buf;
6415         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6416          info->dwVersion);
6417         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6418          "Unexpected size %d\n", info->Issuer.cbData);
6419         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6420          info->Issuer.cbData), "Unexpected value\n");
6421         ok(info->SerialNumber.cbData == sizeof(serialNum),
6422          "Unexpected size %d\n", info->SerialNumber.cbData);
6423         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6424          "Unexpected value\n");
6425         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6426          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6427         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6428          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6429         LocalFree(buf);
6430     }
6431     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6432      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6433      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6434     if (buf)
6435     {
6436         info = (CMSG_SIGNER_INFO *)buf;
6437         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6438          info->dwVersion);
6439         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6440          "Unexpected size %d\n", info->Issuer.cbData);
6441         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6442          info->Issuer.cbData), "Unexpected value\n");
6443         ok(info->SerialNumber.cbData == sizeof(serialNum),
6444          "Unexpected size %d\n", info->SerialNumber.cbData);
6445         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6446          "Unexpected value\n");
6447         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6448          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6449         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6450          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6451         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6452          info->EncryptedHash.cbData);
6453         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6454          "Unexpected value\n");
6455         LocalFree(buf);
6456     }
6457     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6458      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6459      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6460     if (buf)
6461     {
6462         info = (CMSG_SIGNER_INFO *)buf;
6463         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6464          info->AuthAttrs.cAttr);
6465         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6466          "Expected %s, got %s\n", szOID_COMMON_NAME,
6467          info->AuthAttrs.rgAttr[0].pszObjId);
6468         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6469          info->AuthAttrs.rgAttr[0].cValue);
6470         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6471          sizeof(encodedCommonName), "Unexpected size %d\n",
6472          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6473         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6474          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6475         LocalFree(buf);
6476     }
6477 }
6478
6479 static const BYTE CMSSignerWithKeyId[] = {
6480 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6481 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6482
6483 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6484 {
6485     BOOL ret;
6486     LPBYTE buf = NULL;
6487     DWORD size = 0;
6488     CMSG_CMS_SIGNER_INFO info = { 0 };
6489     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6490
6491     SetLastError(0xdeadbeef);
6492     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6493      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6494     ok(!ret, "Expected failure, got %d\n", ret);
6495     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6496     {
6497         skip("no CMS_SIGNER_INFO encode support\n");
6498         return;
6499     }
6500     ok(GetLastError() == E_INVALIDARG,
6501        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6502     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6503     SetLastError(0xdeadbeef);
6504     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6505      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6506     ok(!ret, "Expected failure, got %d\n", ret);
6507     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6508     {
6509         skip("no CMS_SIGNER_INFO encode support\n");
6510         return;
6511     }
6512     ok(GetLastError() == E_INVALIDARG,
6513        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6514     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6515      * be a key id or a issuer serial number with at least the issuer set, and
6516      * the encoding must include PKCS_7_ASN_ENCODING.
6517      * (That isn't enough to be decoded, see decoding tests.)
6518      */
6519     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6520      sizeof(encodedCommonNameNoNull);
6521     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6522     SetLastError(0xdeadbeef);
6523     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6524      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6525     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6526         ok(!ret && GetLastError() == E_INVALIDARG,
6527          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6528     else
6529     {
6530         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6531         if (buf)
6532         {
6533             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6534             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6535             LocalFree(buf);
6536         }
6537     }
6538     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6539     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6540     SetLastError(0xdeadbeef);
6541     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6542      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6543     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6544         ok(!ret && GetLastError() == E_INVALIDARG,
6545          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6546     else
6547     {
6548         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6549         if (buf)
6550         {
6551             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6552              size);
6553             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6554             LocalFree(buf);
6555         }
6556     }
6557     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6558     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6559     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6560     SetLastError(0xdeadbeef);
6561     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6562      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6563     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6564         ok(!ret && GetLastError() == E_INVALIDARG,
6565          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6566     else
6567     {
6568         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6569         if (buf)
6570         {
6571             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6572              size);
6573             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6574             LocalFree(buf);
6575         }
6576     }
6577     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6578      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6579      * (see RFC 3852, section 5.3.)
6580      */
6581     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6582     U(info.SignerId).HashId.cbData = sizeof(hash);
6583     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6584     SetLastError(0xdeadbeef);
6585     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6586      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6587     ok(!ret && GetLastError() == E_INVALIDARG,
6588      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6589     /* Now with a hash algo */
6590     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6591     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6592      sizeof(encodedCommonNameNoNull);
6593     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6594     info.HashAlgorithm.pszObjId = oid1;
6595     SetLastError(0xdeadbeef);
6596     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6597      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6598     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6599         ok(!ret && GetLastError() == E_INVALIDARG,
6600          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6601     else
6602     {
6603         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6604         if (buf)
6605         {
6606             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6607              size);
6608             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6609              "Unexpected value\n");
6610             LocalFree(buf);
6611         }
6612     }
6613     info.HashEncryptionAlgorithm.pszObjId = oid2;
6614     SetLastError(0xdeadbeef);
6615     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6616      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6617     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6618         ok(!ret && GetLastError() == E_INVALIDARG,
6619          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6620     else
6621     {
6622         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6623         if (buf)
6624         {
6625             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6626              "Unexpected size %d\n", size);
6627             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6628              "Unexpected value\n");
6629             LocalFree(buf);
6630         }
6631     }
6632     info.EncryptedHash.cbData = sizeof(hash);
6633     info.EncryptedHash.pbData = (BYTE *)hash;
6634     SetLastError(0xdeadbeef);
6635     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6636      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6637     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6638         ok(!ret && GetLastError() == E_INVALIDARG,
6639          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6640     else
6641     {
6642         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6643         if (buf)
6644         {
6645             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6646              size);
6647             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6648             LocalFree(buf);
6649         }
6650     }
6651 }
6652
6653 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6654 {
6655     BOOL ret;
6656     LPBYTE buf = NULL;
6657     DWORD size = 0;
6658     CMSG_CMS_SIGNER_INFO *info;
6659     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6660
6661     /* A CMS signer can't be decoded without a serial number. */
6662     SetLastError(0xdeadbeef);
6663     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6664      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6665      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6666     ok(!ret, "expected failure\n");
6667     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6668     {
6669         skip("no CMS_SIGNER_INFO decode support\n");
6670         return;
6671     }
6672     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6673      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6674     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6675      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6676      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6677     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6678     if (buf)
6679     {
6680         info = (CMSG_CMS_SIGNER_INFO *)buf;
6681         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6682          info->dwVersion);
6683         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6684          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6685          info->SignerId.dwIdChoice);
6686         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6687          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6688          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6689         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6690          encodedCommonNameNoNull,
6691          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6692          "Unexpected value\n");
6693         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6694          sizeof(serialNum), "Unexpected size %d\n",
6695          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6696         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6697          serialNum, sizeof(serialNum)), "Unexpected value\n");
6698         LocalFree(buf);
6699     }
6700     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6701      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6702      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6703     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6704     if (buf)
6705     {
6706         info = (CMSG_CMS_SIGNER_INFO *)buf;
6707         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6708          info->dwVersion);
6709         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6710          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6711          info->SignerId.dwIdChoice);
6712         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6713          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6714          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6715         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6716          encodedCommonNameNoNull,
6717          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6718          "Unexpected value\n");
6719         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6720          sizeof(serialNum), "Unexpected size %d\n",
6721          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6722         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6723          serialNum, sizeof(serialNum)), "Unexpected value\n");
6724         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6725          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6726         LocalFree(buf);
6727     }
6728     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6729      PKCSSignerWithHashAndEncryptionAlgo,
6730      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6731      NULL, (BYTE *)&buf, &size);
6732     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6733     if (buf)
6734     {
6735         info = (CMSG_CMS_SIGNER_INFO *)buf;
6736         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6737          info->dwVersion);
6738         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6739          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6740          info->SignerId.dwIdChoice);
6741         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6742          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6743          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6744         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6745          encodedCommonNameNoNull,
6746          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6747          "Unexpected value\n");
6748         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6749          sizeof(serialNum), "Unexpected size %d\n",
6750          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6751         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6752          serialNum, sizeof(serialNum)), "Unexpected value\n");
6753         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6754          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6755         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6756          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6757         LocalFree(buf);
6758     }
6759     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6760      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6761      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6762     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6763     if (buf)
6764     {
6765         info = (CMSG_CMS_SIGNER_INFO *)buf;
6766         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6767          info->dwVersion);
6768         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6769          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6770          info->SignerId.dwIdChoice);
6771         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6772          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6773          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6774         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6775          encodedCommonNameNoNull,
6776          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6777          "Unexpected value\n");
6778         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6779          sizeof(serialNum), "Unexpected size %d\n",
6780          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6781         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6782          serialNum, sizeof(serialNum)), "Unexpected value\n");
6783         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6784          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6785         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6786          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6787         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6788          info->EncryptedHash.cbData);
6789         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6790          "Unexpected value\n");
6791         LocalFree(buf);
6792     }
6793     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6794      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6795      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6796     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6797     if (buf)
6798     {
6799         info = (CMSG_CMS_SIGNER_INFO *)buf;
6800         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6801          info->dwVersion);
6802         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6803          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6804          info->SignerId.dwIdChoice);
6805         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6806          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6807         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6808          "Unexpected value\n");
6809         LocalFree(buf);
6810     }
6811 }
6812
6813 static BYTE emptyDNSPermittedConstraints[] = {
6814 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6815 static BYTE emptyDNSExcludedConstraints[] = {
6816 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6817 static BYTE DNSExcludedConstraints[] = {
6818 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6819 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6820 static BYTE permittedAndExcludedConstraints[] = {
6821 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6822 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6823 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6824 static BYTE permittedAndExcludedWithMinConstraints[] = {
6825 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6826 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6827 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6828 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6829 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6830 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6831 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6832
6833 static void test_encodeNameConstraints(DWORD dwEncoding)
6834 {
6835     BOOL ret;
6836     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6837     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6838     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6839     LPBYTE buf;
6840     DWORD size;
6841
6842     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6843      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6844     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6845     {
6846         skip("no X509_NAME_CONSTRAINTS encode support\n");
6847         return;
6848     }
6849     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6850     if (ret)
6851     {
6852         ok(size == sizeof(emptySequence), "Unexpected size\n");
6853         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6854         LocalFree(buf);
6855     }
6856     constraints.cPermittedSubtree = 1;
6857     constraints.rgPermittedSubtree = &permitted;
6858     SetLastError(0xdeadbeef);
6859     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6860      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6861     ok(!ret && GetLastError() == E_INVALIDARG,
6862      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6863     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6864     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6865      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6866     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6867     if (ret)
6868     {
6869         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6870         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6871          "Unexpected value\n");
6872         LocalFree(buf);
6873     }
6874     constraints.cPermittedSubtree = 0;
6875     constraints.cExcludedSubtree = 1;
6876     constraints.rgExcludedSubtree = &excluded;
6877     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6878     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6879      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6880     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6881     if (ret)
6882     {
6883         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6884         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6885          "Unexpected value\n");
6886         LocalFree(buf);
6887     }
6888     U(excluded.Base).pwszURL = (LPWSTR)url;
6889     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6890      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6891     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6892     if (ret)
6893     {
6894         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6895         ok(!memcmp(buf, DNSExcludedConstraints, size),
6896          "Unexpected value\n");
6897         LocalFree(buf);
6898     }
6899     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6900     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6901     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6902     constraints.cPermittedSubtree = 1;
6903     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6904      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6905     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6906     if (ret)
6907     {
6908         ok(size == sizeof(permittedAndExcludedConstraints),
6909          "Unexpected size\n");
6910         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6911          "Unexpected value\n");
6912         LocalFree(buf);
6913     }
6914     permitted.dwMinimum = 5;
6915     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6916      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6918     if (ret)
6919     {
6920         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6921          "Unexpected size\n");
6922         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6923          "Unexpected value\n");
6924         LocalFree(buf);
6925     }
6926     permitted.fMaximum = TRUE;
6927     permitted.dwMaximum = 3;
6928     SetLastError(0xdeadbeef);
6929     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6930      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6931     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6932     if (ret)
6933     {
6934         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6935          "Unexpected size\n");
6936         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6937          "Unexpected value\n");
6938         LocalFree(buf);
6939     }
6940 }
6941
6942 struct EncodedNameConstraints
6943 {
6944     CRYPT_DATA_BLOB            encoded;
6945     CERT_NAME_CONSTRAINTS_INFO constraints;
6946 };
6947
6948 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6949  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6950 static CERT_GENERAL_SUBTREE DNSSubtree = {
6951  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6952 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6953  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6954 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6955  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6956 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6957  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6958
6959 struct EncodedNameConstraints encodedNameConstraints[] = {
6960  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6961  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6962    { 1, &emptyDNSSubtree, 0, NULL } },
6963  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6964    { 0, NULL, 1, &emptyDNSSubtree } },
6965  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6966    { 0, NULL, 1, &DNSSubtree } },
6967  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6968    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6969  { { sizeof(permittedAndExcludedWithMinConstraints),
6970      permittedAndExcludedWithMinConstraints },
6971    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6972  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6973      permittedAndExcludedWithMinMaxConstraints },
6974    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6975 };
6976
6977 static void test_decodeNameConstraints(DWORD dwEncoding)
6978 {
6979     BOOL ret;
6980     DWORD i;
6981     CERT_NAME_CONSTRAINTS_INFO *constraints;
6982
6983     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6984     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6985     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6986     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6987     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6988     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6989     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6990     for (i = 0;
6991      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6992      i++)
6993     {
6994         DWORD size;
6995
6996         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6997          encodedNameConstraints[i].encoded.pbData,
6998          encodedNameConstraints[i].encoded.cbData,
6999          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7000         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7001         {
7002             skip("no X509_NAME_CONSTRAINTS decode support\n");
7003             return;
7004         }
7005         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7006         if (ret)
7007         {
7008             DWORD j;
7009
7010             if (constraints->cPermittedSubtree !=
7011              encodedNameConstraints[i].constraints.cPermittedSubtree)
7012                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7013                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7014                  constraints->cPermittedSubtree);
7015             if (constraints->cPermittedSubtree ==
7016              encodedNameConstraints[i].constraints.cPermittedSubtree)
7017             {
7018                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7019                 {
7020                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7021                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7022                 }
7023             }
7024             if (constraints->cExcludedSubtree !=
7025              encodedNameConstraints[i].constraints.cExcludedSubtree)
7026                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7027                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7028                  constraints->cExcludedSubtree);
7029             if (constraints->cExcludedSubtree ==
7030              encodedNameConstraints[i].constraints.cExcludedSubtree)
7031             {
7032                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7033                 {
7034                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7035                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7036                 }
7037             }
7038             LocalFree(constraints);
7039         }
7040     }
7041 }
7042
7043 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7044  'n','o','t','i','c','e',0 };
7045 static const BYTE noticeWithDisplayText[] = {
7046  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7047  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7048  0x00,0x69,0x00,0x63,0x00,0x65
7049 };
7050 static char org[] = "Wine";
7051 static int noticeNumbers[] = { 2,3 };
7052 static BYTE noticeWithReference[] = {
7053  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7054  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7055  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7056  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7057 };
7058
7059 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7060 {
7061     BOOL ret;
7062     LPBYTE buf;
7063     DWORD size;
7064     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7065     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7066
7067     memset(&notice, 0, sizeof(notice));
7068     ret = pCryptEncodeObjectEx(dwEncoding,
7069      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7070      NULL, &buf, &size);
7071     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7072     {
7073         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7074         return;
7075     }
7076     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7077     if (ret)
7078     {
7079         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7080         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7081         LocalFree(buf);
7082     }
7083     notice.pszDisplayText = noticeText;
7084     ret = pCryptEncodeObjectEx(dwEncoding,
7085      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7086      NULL, &buf, &size);
7087     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7088     if (ret)
7089     {
7090         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7091         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7092         LocalFree(buf);
7093     }
7094     reference.pszOrganization = org;
7095     reference.cNoticeNumbers = 2;
7096     reference.rgNoticeNumbers = noticeNumbers;
7097     notice.pNoticeReference = &reference;
7098     ret = pCryptEncodeObjectEx(dwEncoding,
7099      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7100      NULL, &buf, &size);
7101     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7102     if (ret)
7103     {
7104         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7105         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7106         LocalFree(buf);
7107     }
7108 }
7109
7110 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7111 {
7112     BOOL ret;
7113     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7114     DWORD size;
7115
7116     ret = pCryptDecodeObjectEx(dwEncoding,
7117      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7118      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7119      &notice, &size);
7120     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7121     {
7122         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7123         return;
7124     }
7125     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7126     if (ret)
7127     {
7128         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7129         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7130         LocalFree(notice);
7131     }
7132     ret = pCryptDecodeObjectEx(dwEncoding,
7133      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7134      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7135      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7136     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7137     if (ret)
7138     {
7139         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7140          "unexpected display text\n");
7141         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7142         LocalFree(notice);
7143     }
7144     ret = pCryptDecodeObjectEx(dwEncoding,
7145      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7146      noticeWithReference, sizeof(noticeWithReference),
7147      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7148     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7149     if (ret)
7150     {
7151         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7152          "unexpected display text\n");
7153         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7154         if (notice->pNoticeReference)
7155         {
7156             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7157              "unexpected organization %s\n",
7158              notice->pNoticeReference->pszOrganization);
7159             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7160              "expected 2 notice numbers, got %d\n",
7161              notice->pNoticeReference->cNoticeNumbers);
7162             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7163              "unexpected notice number %d\n",
7164              notice->pNoticeReference->rgNoticeNumbers[0]);
7165             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7166              "unexpected notice number %d\n",
7167              notice->pNoticeReference->rgNoticeNumbers[1]);
7168         }
7169         LocalFree(notice);
7170     }
7171 }
7172
7173 static char oid_any_policy[] = "2.5.29.32.0";
7174 static const BYTE policiesWithAnyPolicy[] = {
7175  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7176 };
7177 static char oid1[] = "1.2.3";
7178 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7179 static const BYTE twoPolicies[] = {
7180  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7181  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7182  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7183  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7184  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7185  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7186 };
7187
7188 static void test_encodeCertPolicies(DWORD dwEncoding)
7189 {
7190     BOOL ret;
7191     CERT_POLICIES_INFO info;
7192     CERT_POLICY_INFO policy[2];
7193     CERT_POLICY_QUALIFIER_INFO qualifier;
7194     LPBYTE buf;
7195     DWORD size;
7196
7197     memset(&info, 0, sizeof(info));
7198     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7199      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7200     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7201     if (ret)
7202     {
7203         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7204         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7205         LocalFree(buf);
7206     }
7207     memset(policy, 0, sizeof(policy));
7208     info.cPolicyInfo = 1;
7209     info.rgPolicyInfo = policy;
7210     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7211      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7212     ok(!ret && (GetLastError() == E_INVALIDARG ||
7213      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7214      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7215     policy[0].pszPolicyIdentifier = oid_any_policy;
7216     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7217      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7218     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7219     if (ret)
7220     {
7221         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7222         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7223         LocalFree(buf);
7224     }
7225     policy[1].pszPolicyIdentifier = oid1;
7226     memset(&qualifier, 0, sizeof(qualifier));
7227     qualifier.pszPolicyQualifierId = oid_user_notice;
7228     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7229     qualifier.Qualifier.pbData = noticeWithReference;
7230     policy[1].cPolicyQualifier = 1;
7231     policy[1].rgPolicyQualifier = &qualifier;
7232     info.cPolicyInfo = 2;
7233     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7234      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7235     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7236     if (ret)
7237     {
7238         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7239         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7240         LocalFree(buf);
7241     }
7242 }
7243
7244 static void test_decodeCertPolicies(DWORD dwEncoding)
7245 {
7246     BOOL ret;
7247     CERT_POLICIES_INFO *info;
7248     DWORD size;
7249
7250     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7251      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7252      &info, &size);
7253     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7254     if (ret)
7255     {
7256         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7257          info->cPolicyInfo);
7258         LocalFree(info);
7259     }
7260     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7261      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7262      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7263     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7264     if (ret)
7265     {
7266         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7267          info->cPolicyInfo);
7268         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7269          "unexpected policy id %s\n",
7270          info->rgPolicyInfo[0].pszPolicyIdentifier);
7271         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7272          "unexpected policy qualifier count %d\n",
7273          info->rgPolicyInfo[0].cPolicyQualifier);
7274         LocalFree(info);
7275     }
7276     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7277      twoPolicies, sizeof(twoPolicies),
7278      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7279     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7280     if (ret)
7281     {
7282         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7283          info->cPolicyInfo);
7284         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7285          "unexpected policy id %s\n",
7286          info->rgPolicyInfo[0].pszPolicyIdentifier);
7287         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7288          "unexpected policy qualifier count %d\n",
7289          info->rgPolicyInfo[0].cPolicyQualifier);
7290         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7291          "unexpected policy id %s\n",
7292          info->rgPolicyInfo[1].pszPolicyIdentifier);
7293         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7294          "unexpected policy qualifier count %d\n",
7295          info->rgPolicyInfo[1].cPolicyQualifier);
7296         ok(!strcmp(
7297          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7298          oid_user_notice), "unexpected policy qualifier id %s\n",
7299          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7300         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7301          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7302          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7303         ok(!memcmp(
7304          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7305          noticeWithReference, sizeof(noticeWithReference)),
7306          "unexpected qualifier value\n");
7307         LocalFree(info);
7308     }
7309 }
7310
7311 /* Free *pInfo with HeapFree */
7312 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7313 {
7314     BOOL ret;
7315     DWORD size = 0;
7316     HCRYPTKEY key;
7317
7318     /* This crashes
7319     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7320      */
7321     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7322     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7323      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7324     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7325      &size);
7326     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7327      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7328     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7329      NULL, &size);
7330     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7331      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7332     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7333      0, NULL, NULL, &size);
7334     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7335      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7336     /* Test with no key */
7337     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7338      0, NULL, NULL, &size);
7339     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7340      GetLastError());
7341     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7342     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7343     if (ret)
7344     {
7345         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7346          NULL, 0, NULL, NULL, &size);
7347         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7348         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7349         if (*pInfo)
7350         {
7351             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7352              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7353             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7354              GetLastError());
7355             if (ret)
7356             {
7357                 /* By default (we passed NULL as the OID) the OID is
7358                  * szOID_RSA_RSA.
7359                  */
7360                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7361                  "Expected %s, got %s\n", szOID_RSA_RSA,
7362                  (*pInfo)->Algorithm.pszObjId);
7363             }
7364         }
7365     }
7366     CryptDestroyKey(key);
7367 }
7368
7369 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7370  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7371  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7372  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7373  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7374  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7375  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7376  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7377  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7378  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7379  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7380  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7381  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7382  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7383  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7384  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7385  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7386  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7387  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7388  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7389  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7390  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7391  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7392  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7393  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7394
7395 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7396 {
7397     BOOL ret;
7398     HCRYPTKEY key;
7399     PCCERT_CONTEXT context;
7400     DWORD dwSize;
7401     ALG_ID ai;
7402
7403     /* These crash
7404     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7405     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7406     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7407     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7408      NULL);
7409      */
7410     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7411     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7412      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7413     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7414     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7415      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7416     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7417      &key);
7418     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7419      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7420
7421     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7422     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7423      &key);
7424     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7425
7426     dwSize = sizeof(ai);
7427     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7428     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7429     if(ret)
7430     {
7431       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7432       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7433     }
7434
7435     CryptDestroyKey(key);
7436
7437     /* Repeat with forced algorithm */
7438     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7439      &key);
7440     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7441
7442     dwSize = sizeof(ai);
7443     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7444     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7445     if(ret)
7446     {
7447       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7448       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7449     }
7450
7451     CryptDestroyKey(key);
7452
7453     /* Test importing a public key from a certificate context */
7454     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7455      sizeof(expiredCert));
7456     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7457      GetLastError());
7458     if (context)
7459     {
7460         ok(!strcmp(szOID_RSA_RSA,
7461          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7462          "Expected %s, got %s\n", szOID_RSA_RSA,
7463          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7464         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7465          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7466         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7467         CryptDestroyKey(key);
7468         CertFreeCertificateContext(context);
7469     }
7470 }
7471
7472 static const char cspName[] = "WineCryptTemp";
7473
7474 static void testPortPublicKeyInfo(void)
7475 {
7476     HCRYPTPROV csp;
7477     BOOL ret;
7478     PCERT_PUBLIC_KEY_INFO info = NULL;
7479
7480     /* Just in case a previous run failed, delete this thing */
7481     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7482      CRYPT_DELETEKEYSET);
7483     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7484      CRYPT_NEWKEYSET);
7485
7486     testExportPublicKey(csp, &info);
7487     testImportPublicKey(csp, info);
7488
7489     HeapFree(GetProcessHeap(), 0, info);
7490     CryptReleaseContext(csp, 0);
7491     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7492      CRYPT_DELETEKEYSET);
7493 }
7494
7495 START_TEST(encode)
7496 {
7497     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7498      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7499     HMODULE hCrypt32;
7500     DWORD i;
7501
7502     hCrypt32 = GetModuleHandleA("crypt32.dll");
7503     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7504     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7505     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7506     {
7507         skip("CryptDecodeObjectEx() is not available\n");
7508         return;
7509     }
7510
7511     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7512     {
7513         test_encodeInt(encodings[i]);
7514         test_decodeInt(encodings[i]);
7515         test_encodeEnumerated(encodings[i]);
7516         test_decodeEnumerated(encodings[i]);
7517         test_encodeFiletime(encodings[i]);
7518         test_decodeFiletime(encodings[i]);
7519         test_encodeName(encodings[i]);
7520         test_decodeName(encodings[i]);
7521         test_encodeUnicodeName(encodings[i]);
7522         test_decodeUnicodeName(encodings[i]);
7523         test_encodeNameValue(encodings[i]);
7524         test_decodeNameValue(encodings[i]);
7525         test_encodeUnicodeNameValue(encodings[i]);
7526         test_decodeUnicodeNameValue(encodings[i]);
7527         test_encodeAltName(encodings[i]);
7528         test_decodeAltName(encodings[i]);
7529         test_encodeOctets(encodings[i]);
7530         test_decodeOctets(encodings[i]);
7531         test_encodeBits(encodings[i]);
7532         test_decodeBits(encodings[i]);
7533         test_encodeBasicConstraints(encodings[i]);
7534         test_decodeBasicConstraints(encodings[i]);
7535         test_encodeRsaPublicKey(encodings[i]);
7536         test_decodeRsaPublicKey(encodings[i]);
7537         test_encodeSequenceOfAny(encodings[i]);
7538         test_decodeSequenceOfAny(encodings[i]);
7539         test_encodeExtensions(encodings[i]);
7540         test_decodeExtensions(encodings[i]);
7541         test_encodePublicKeyInfo(encodings[i]);
7542         test_decodePublicKeyInfo(encodings[i]);
7543         test_encodeCertToBeSigned(encodings[i]);
7544         test_decodeCertToBeSigned(encodings[i]);
7545         test_encodeCert(encodings[i]);
7546         test_decodeCert(encodings[i]);
7547         test_encodeCRLDistPoints(encodings[i]);
7548         test_decodeCRLDistPoints(encodings[i]);
7549         test_encodeCRLIssuingDistPoint(encodings[i]);
7550         test_decodeCRLIssuingDistPoint(encodings[i]);
7551         test_encodeCRLToBeSigned(encodings[i]);
7552         test_decodeCRLToBeSigned(encodings[i]);
7553         test_encodeEnhancedKeyUsage(encodings[i]);
7554         test_decodeEnhancedKeyUsage(encodings[i]);
7555         test_encodeAuthorityKeyId(encodings[i]);
7556         test_decodeAuthorityKeyId(encodings[i]);
7557         test_encodeAuthorityKeyId2(encodings[i]);
7558         test_decodeAuthorityKeyId2(encodings[i]);
7559         test_encodeAuthorityInfoAccess(encodings[i]);
7560         test_decodeAuthorityInfoAccess(encodings[i]);
7561         test_encodeCTL(encodings[i]);
7562         test_decodeCTL(encodings[i]);
7563         test_encodePKCSContentInfo(encodings[i]);
7564         test_decodePKCSContentInfo(encodings[i]);
7565         test_encodePKCSAttribute(encodings[i]);
7566         test_decodePKCSAttribute(encodings[i]);
7567         test_encodePKCSAttributes(encodings[i]);
7568         test_decodePKCSAttributes(encodings[i]);
7569         test_encodePKCSSMimeCapabilities(encodings[i]);
7570         test_decodePKCSSMimeCapabilities(encodings[i]);
7571         test_encodePKCSSignerInfo(encodings[i]);
7572         test_decodePKCSSignerInfo(encodings[i]);
7573         test_encodeCMSSignerInfo(encodings[i]);
7574         test_decodeCMSSignerInfo(encodings[i]);
7575         test_encodeNameConstraints(encodings[i]);
7576         test_decodeNameConstraints(encodings[i]);
7577         test_encodePolicyQualifierUserNotice(encodings[i]);
7578         test_decodePolicyQualifierUserNotice(encodings[i]);
7579         test_encodeCertPolicies(encodings[i]);
7580         test_decodeCertPolicies(encodings[i]);
7581     }
7582     testPortPublicKeyInfo();
7583 }