d3d8/tests: Get rid of struct vertex.
[wine.git] / dlls / crypt32 / tests / encode.c
blob532c3220b32be6a9814da35f0a2755dc92ef6989
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
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.
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.
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
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
27 #include "wine/test.h"
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*);
33 struct encodedInt
35 int val;
36 const BYTE *encoded;
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};
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 },
57 struct encodedBigInt
59 const BYTE *val;
60 const BYTE *encoded;
61 const BYTE *decoded;
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};
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};
72 static const struct encodedBigInt bigInts[] = {
73 { bin8, bin9, bin10 },
74 { bin11, bin12, bin13 },
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};
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 },
88 static void test_encodeInt(DWORD dwEncoding)
90 DWORD bufSize = 0;
91 int i;
92 BOOL ret;
93 CRYPT_INTEGER_BLOB blob;
94 BYTE *buf = NULL;
96 /* CryptEncodeObjectEx with NULL bufSize crashes..
97 ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 NULL);
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)
107 /* check with NULL integer buffer. Windows XP incorrectly returns an
108 * NTSTATUS (crashes on win9x).
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());
115 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
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 (ret)
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);
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 (ret)
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);
154 /* encode a couple bigger ints, just to show it's little-endian and leading
155 * sign bytes are dropped
157 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
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 (ret)
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);
179 /* and, encode some uints */
180 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
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 (ret)
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);
204 static void test_decodeInt(DWORD dwEncoding)
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;
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);
220 /* check bogus encoding */
221 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* check with NULL integer buffer */
226 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227 &bufSize);
228 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229 GetLastError() == OSS_BAD_ARG /* Win9x */),
230 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231 /* check with a valid, but too large, integer */
232 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234 ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235 broken(ret) /* Win9x */,
236 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237 /* check with a DER-encoded string */
238 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243 GetLastError());
244 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
246 /* When the output buffer is NULL, this always succeeds */
247 SetLastError(0xdeadbeef);
248 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250 &bufSize);
251 ok(ret && GetLastError() == NOERROR,
252 "Expected success and NOERROR, got %d\n", GetLastError());
253 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254 ints[i].encoded, ints[i].encoded[1] + 2,
255 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258 ok(buf != NULL, "Expected allocated buffer\n");
259 if (ret)
261 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262 ints[i].val, *(int *)buf);
263 LocalFree(buf);
266 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
268 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270 &bufSize);
271 ok(ret && GetLastError() == NOERROR,
272 "Expected success and NOERROR, got %d\n", GetLastError());
273 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278 ok(buf != NULL, "Expected allocated buffer\n");
279 if (ret)
281 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
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);
291 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
293 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295 &bufSize);
296 ok(ret && GetLastError() == NOERROR,
297 "Expected success and NOERROR, got %d\n", GetLastError());
298 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303 ok(buf != NULL, "Expected allocated buffer\n");
304 if (ret)
306 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
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);
316 /* Decode the value 1 with long-form length */
317 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320 if (ret)
322 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323 LocalFree(buf);
325 /* check with extra bytes at the end */
326 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329 if (ret)
331 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332 LocalFree(buf);
334 /* Try to decode some bogus large items */
335 /* The buffer size is smaller than the encoded length, so this should fail
336 * with CRYPT_E_ASN1_EOD if it's being decoded.
337 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339 * So this test unfortunately isn't useful.
340 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
345 /* This will try to decode the buffer and overflow it, check that it's
346 * caught.
348 if (0)
350 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
361 /* These are always encoded unsigned, and aren't constrained to be any
362 * particular value
364 static const struct encodedInt enums[] = {
365 { 1, bin18 },
366 { -128, bin19 },
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370 * X509_ENUMERATED.
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373 szOID_CRL_REASON_CODE };
375 static void test_encodeEnumerated(DWORD dwEncoding)
377 DWORD i, j;
379 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
381 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
383 BOOL ret;
384 BYTE *buf = NULL;
385 DWORD bufSize = 0;
387 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389 &bufSize);
390 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391 if (ret)
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);
408 static void test_decodeEnumerated(DWORD dwEncoding)
410 DWORD i, j;
412 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
414 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
416 BOOL ret;
417 DWORD bufSize = sizeof(int);
418 int val;
420 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422 &val, &bufSize);
423 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424 ok(bufSize == sizeof(int),
425 "Got unexpected size %d for enumerated\n", bufSize);
426 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427 val, enums[j].val);
432 struct encodedFiletime
434 SYSTEMTIME sysTime;
435 const BYTE *encodedTime;
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439 const struct encodedFiletime *time)
441 FILETIME ft = { 0 };
442 BYTE *buf = NULL;
443 DWORD bufSize = 0;
444 BOOL ret;
446 ret = SystemTimeToFileTime(&time->sysTime, &ft);
447 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450 /* years other than 1950-2050 are not allowed for encodings other than
451 * X509_CHOICE_OF_TIME.
453 if (structType == X509_CHOICE_OF_TIME ||
454 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
456 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457 GetLastError());
458 ok(buf != NULL, "Expected an allocated buffer\n");
459 if (ret)
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);
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());
477 static const char *printSystemTime(const SYSTEMTIME *st)
479 static char buf[25];
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;
486 static const char *printFileTime(const FILETIME *ft)
488 static char buf[25];
489 SYSTEMTIME st;
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;
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
499 SYSTEMTIME st;
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.
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));
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521 const struct encodedFiletime *time)
523 FILETIME ft = { 0 };
524 DWORD size = sizeof(ft);
525 BOOL ret;
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.
532 if (structType == X509_CHOICE_OF_TIME ||
533 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
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);
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());
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'};
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 },
561 static void test_encodeFiletime(DWORD dwEncoding)
563 DWORD i;
565 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
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]);
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'};
606 static void test_decodeFiletime(DWORD dwEncoding)
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 },
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" },
625 static const unsigned char *bogusTimes[] = {
626 /* oddly, this succeeds on Windows, with year 2765
627 "\x18" "\x0f" "21r50606161000Z",
629 bin35,
630 bin36,
631 bin37,
632 bin38,
634 DWORD i, size;
635 FILETIME ft1 = { 0 }, ft2 = { 0 };
636 BOOL ret;
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++)
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]);
653 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
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]);
659 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
661 size = sizeof(ft1);
662 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665 GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666 broken(ret), /* Win9x and NT4 for bin38 */
667 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668 GetLastError());
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690 0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692 0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694 0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698 0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
702 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
705 static CHAR oid_us[] = "2.5.4.6",
706 oid_minnesota[] = "2.5.4.8",
707 oid_minneapolis[] = "2.5.4.7",
708 oid_codeweavers[] = "2.5.4.10",
709 oid_wine[] = "2.5.4.11",
710 oid_localhostAttr[] = "2.5.4.3",
711 oid_aric[] = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713 { RDNA(minnesota) },
714 { RDNA(minneapolis) },
715 { RDNA(codeweavers) },
716 { RDNA(wine) },
717 { RDNA(localhostAttr) },
718 { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720 { RDNA(localhostAttr) },
721 { RDNA(minnesota) },
722 { RDNA(minneapolis) },
723 { RDNA(codeweavers) },
724 { RDNA(wine) },
725 { RDNIA5(aric) } };
727 #undef RDNIA5
728 #undef RDNA
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
743 static void test_encodeName(DWORD dwEncoding)
745 CERT_RDN_ATTR attrs[2];
746 CERT_RDN rdn;
747 CERT_NAME_INFO info;
748 static CHAR oid_common_name[] = szOID_COMMON_NAME,
749 oid_sur_name[] = szOID_SUR_NAME;
750 BYTE *buf = NULL;
751 DWORD size = 0;
752 BOOL ret;
754 if (0)
756 /* Test with NULL pvStructInfo (crashes on win9x) */
757 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
762 /* Test with empty CERT_NAME_INFO */
763 info.cRDN = 0;
764 info.rgRDN = NULL;
765 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768 if (ret)
770 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771 "Got unexpected encoding for empty name\n");
772 LocalFree(buf);
774 if (0)
776 /* Test with bogus CERT_RDN (crashes on win9x) */
777 info.cRDN = 1;
778 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
783 /* Test with empty CERT_RDN */
784 rdn.cRDNAttr = 0;
785 rdn.rgRDNAttr = NULL;
786 info.cRDN = 1;
787 info.rgRDN = &rdn;
788 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791 if (ret)
793 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794 "Got unexpected encoding for empty RDN array\n");
795 LocalFree(buf);
797 if (0)
799 /* Test with bogus attr array (crashes on win9x) */
800 rdn.cRDNAttr = 1;
801 rdn.rgRDNAttr = NULL;
802 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
807 /* oddly, a bogus OID is accepted by Windows XP; not testing.
808 attrs[0].pszObjId = "bogus";
809 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810 attrs[0].Value.cbData = sizeof(commonName);
811 attrs[0].Value.pbData = commonName;
812 rdn.cRDNAttr = 1;
813 rdn.rgRDNAttr = attrs;
814 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816 ok(!ret, "Expected failure, got success\n");
818 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
819 * the encoded attributes to be swapped.
821 attrs[0].pszObjId = oid_common_name;
822 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823 attrs[0].Value.cbData = sizeof(commonName);
824 attrs[0].Value.pbData = (BYTE *)commonName;
825 attrs[1].pszObjId = oid_sur_name;
826 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827 attrs[1].Value.cbData = sizeof(surName);
828 attrs[1].Value.pbData = (BYTE *)surName;
829 rdn.cRDNAttr = 2;
830 rdn.rgRDNAttr = attrs;
831 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834 if (ret)
836 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837 "Got unexpected encoding for two RDN array\n");
838 LocalFree(buf);
840 /* A name can be "encoded" with previously encoded RDN attrs. */
841 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843 attrs[0].Value.cbData = sizeof(twoRDNs);
844 rdn.cRDNAttr = 1;
845 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848 if (ret)
850 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851 ok(!memcmp(buf, encodedTwoRDNs, size),
852 "Unexpected value for re-encoded two RDN array\n");
853 LocalFree(buf);
855 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856 rdn.cRDNAttr = 1;
857 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860 ok(!ret && GetLastError() == E_INVALIDARG,
861 "Expected E_INVALIDARG, got %08x\n", GetLastError());
862 /* Test a more complex name */
863 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864 rdn.rgRDNAttr = rdnAttrs;
865 info.cRDN = 1;
866 info.rgRDN = &rdn;
867 buf = NULL;
868 size = 0;
869 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872 if (ret)
874 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876 LocalFree(buf);
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
883 static const BYTE twoRDNsNoNull[] = {
884 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886 0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891 0x61,0x4c,0x67,0x6e };
893 static void test_encodeUnicodeName(DWORD dwEncoding)
895 CERT_RDN_ATTR attrs[2];
896 CERT_RDN rdn;
897 CERT_NAME_INFO info;
898 static CHAR oid_common_name[] = szOID_COMMON_NAME,
899 oid_sur_name[] = szOID_SUR_NAME;
900 BYTE *buf = NULL;
901 DWORD size = 0;
902 BOOL ret;
904 if (0)
906 /* Test with NULL pvStructInfo (crashes on win9x) */
907 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
912 /* Test with empty CERT_NAME_INFO */
913 info.cRDN = 0;
914 info.rgRDN = NULL;
915 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918 if (ret)
920 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921 "Got unexpected encoding for empty name\n");
922 LocalFree(buf);
924 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925 * encoding (the NULL).
927 attrs[0].pszObjId = oid_common_name;
928 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929 attrs[0].Value.cbData = sizeof(commonNameW);
930 attrs[0].Value.pbData = (BYTE *)commonNameW;
931 rdn.cRDNAttr = 1;
932 rdn.rgRDNAttr = attrs;
933 info.cRDN = 1;
934 info.rgRDN = &rdn;
935 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939 ok(size == 9, "Unexpected error index %08x\n", size);
940 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
941 * forces the order of the encoded attributes to be swapped.
943 attrs[0].pszObjId = oid_common_name;
944 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945 attrs[0].Value.cbData = 0;
946 attrs[0].Value.pbData = (BYTE *)commonNameW;
947 attrs[1].pszObjId = oid_sur_name;
948 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949 attrs[1].Value.cbData = 0;
950 attrs[1].Value.pbData = (BYTE *)surNameW;
951 rdn.cRDNAttr = 2;
952 rdn.rgRDNAttr = attrs;
953 info.cRDN = 1;
954 info.rgRDN = &rdn;
955 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958 if (ret)
960 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961 "Got unexpected encoding for two RDN array\n");
962 LocalFree(buf);
964 /* A name can be "encoded" with previously encoded RDN attrs. */
965 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967 attrs[0].Value.cbData = sizeof(twoRDNs);
968 rdn.cRDNAttr = 1;
969 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972 if (ret)
974 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975 ok(!memcmp(buf, encodedTwoRDNs, size),
976 "Unexpected value for re-encoded two RDN array\n");
977 LocalFree(buf);
979 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980 rdn.cRDNAttr = 1;
981 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985 if (ret)
987 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989 LocalFree(buf);
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994 const CERT_NAME_VALUE *got)
996 if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997 got->dwValueType == CERT_RDN_ENCODED_BLOB)
999 win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000 return;
1003 ok(got->dwValueType == expected->dwValueType,
1004 "Expected string type %d, got %d\n", expected->dwValueType,
1005 got->dwValueType);
1006 ok(got->Value.cbData == expected->Value.cbData ||
1007 got->Value.cbData == expected->Value.cbData - sizeof(WCHAR) /* Win8 */,
1008 "String type %d: unexpected data size, got %d, expected %d\n",
1009 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1010 if (got->Value.cbData && got->Value.pbData)
1011 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1012 min(got->Value.cbData, expected->Value.cbData)),
1013 "String type %d: unexpected value\n", expected->dwValueType);
1016 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1017 const CERT_RDN_ATTR *got)
1019 if (expected->pszObjId && strlen(expected->pszObjId))
1021 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1022 expected->pszObjId);
1023 if (got->pszObjId)
1025 ok(!strcmp(got->pszObjId, expected->pszObjId),
1026 "Got unexpected OID %s, expected %s\n", got->pszObjId,
1027 expected->pszObjId);
1030 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1031 (const CERT_NAME_VALUE *)&got->dwValueType);
1034 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1036 ok(got->cRDNAttr == expected->cRDNAttr,
1037 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1038 if (got->cRDNAttr)
1040 DWORD i;
1042 for (i = 0; i < got->cRDNAttr; i++)
1043 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1047 static void compareNames(const CERT_NAME_INFO *expected,
1048 const CERT_NAME_INFO *got)
1050 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1051 expected->cRDN, got->cRDN);
1052 if (got->cRDN)
1054 DWORD i;
1056 for (i = 0; i < got->cRDN; i++)
1057 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1061 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1062 static const BYTE twoRDNsExtraBytes[] = {
1063 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1064 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1065 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1067 static void test_decodeName(DWORD dwEncoding)
1069 BYTE *buf = NULL;
1070 DWORD bufSize = 0;
1071 BOOL ret;
1072 CERT_RDN rdn;
1073 CERT_NAME_INFO info = { 1, &rdn };
1075 /* test empty name */
1076 bufSize = 0;
1077 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1078 emptySequence[1] + 2,
1079 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1080 &buf, &bufSize);
1081 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1082 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
1083 * decoder works the same way, so only test the count.
1085 if (ret)
1087 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1088 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1089 "Expected 0 RDNs in empty info, got %d\n",
1090 ((CERT_NAME_INFO *)buf)->cRDN);
1091 LocalFree(buf);
1093 /* test empty name with indefinite-length encoding */
1094 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1095 sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1096 &buf, &bufSize);
1097 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1098 if (ret)
1100 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1101 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1102 "Expected 0 RDNs in empty info, got %d\n",
1103 ((CERT_NAME_INFO *)buf)->cRDN);
1104 LocalFree(buf);
1106 /* test empty RDN */
1107 bufSize = 0;
1108 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1109 emptyRDNs[1] + 2,
1110 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1111 &buf, &bufSize);
1112 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1113 if (ret)
1115 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1117 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1118 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1119 "Got unexpected value for empty RDN\n");
1120 LocalFree(buf);
1122 /* test two RDN attrs */
1123 bufSize = 0;
1124 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1125 twoRDNs[1] + 2,
1126 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1127 &buf, &bufSize);
1128 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1129 if (ret)
1131 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1132 oid_common_name[] = szOID_COMMON_NAME;
1134 CERT_RDN_ATTR attrs[] = {
1135 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1136 (BYTE *)surName } },
1137 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1138 (BYTE *)commonName } },
1141 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1142 rdn.rgRDNAttr = attrs;
1143 compareNames(&info, (CERT_NAME_INFO *)buf);
1144 LocalFree(buf);
1146 /* test that two RDN attrs with extra bytes succeeds */
1147 bufSize = 0;
1148 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1149 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1150 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1151 /* And, a slightly more complicated name */
1152 buf = NULL;
1153 bufSize = 0;
1154 ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1155 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1156 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1157 if (ret)
1159 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1160 rdn.rgRDNAttr = decodedRdnAttrs;
1161 compareNames(&info, (CERT_NAME_INFO *)buf);
1162 LocalFree(buf);
1166 static void test_decodeUnicodeName(DWORD dwEncoding)
1168 BYTE *buf = NULL;
1169 DWORD bufSize = 0;
1170 BOOL ret;
1171 CERT_RDN rdn;
1172 CERT_NAME_INFO info = { 1, &rdn };
1174 /* test empty name */
1175 bufSize = 0;
1176 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1177 emptySequence[1] + 2,
1178 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1179 &buf, &bufSize);
1180 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1181 if (ret)
1183 ok(bufSize == sizeof(CERT_NAME_INFO),
1184 "Got wrong bufSize %d\n", bufSize);
1185 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1186 "Expected 0 RDNs in empty info, got %d\n",
1187 ((CERT_NAME_INFO *)buf)->cRDN);
1188 LocalFree(buf);
1190 /* test empty RDN */
1191 bufSize = 0;
1192 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1193 emptyRDNs[1] + 2,
1194 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1195 &buf, &bufSize);
1196 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1197 if (ret)
1199 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1201 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1202 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1203 "Got unexpected value for empty RDN\n");
1204 LocalFree(buf);
1206 /* test two RDN attrs */
1207 bufSize = 0;
1208 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1209 sizeof(twoRDNsNoNull),
1210 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1211 &buf, &bufSize);
1212 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1213 if (ret)
1215 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1216 oid_common_name[] = szOID_COMMON_NAME;
1218 CERT_RDN_ATTR attrs[] = {
1219 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1220 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1221 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1222 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1225 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1226 rdn.rgRDNAttr = attrs;
1227 compareNames(&info, (CERT_NAME_INFO *)buf);
1228 LocalFree(buf);
1232 struct EncodedNameValue
1234 CERT_NAME_VALUE value;
1235 const BYTE *encoded;
1236 DWORD encodedSize;
1239 static const char bogusIA5[] = "\x80";
1240 static const char bogusPrintable[] = "~";
1241 static const char bogusNumeric[] = "A";
1242 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1243 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1244 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1245 static BYTE octetCommonNameValue[] = {
1246 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1247 static BYTE numericCommonNameValue[] = {
1248 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1249 static BYTE printableCommonNameValue[] = {
1250 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1251 static BYTE t61CommonNameValue[] = {
1252 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1253 static BYTE videotexCommonNameValue[] = {
1254 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1255 static BYTE ia5CommonNameValue[] = {
1256 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1257 static BYTE graphicCommonNameValue[] = {
1258 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1259 static BYTE visibleCommonNameValue[] = {
1260 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1261 static BYTE generalCommonNameValue[] = {
1262 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1263 static BYTE bmpCommonNameValue[] = {
1264 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1265 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1266 static BYTE utf8CommonNameValue[] = {
1267 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1268 static char embedded_null[] = "foo\0com";
1269 static BYTE ia5EmbeddedNull[] = {
1270 0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1272 static struct EncodedNameValue nameValues[] = {
1273 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274 octetCommonNameValue, sizeof(octetCommonNameValue) },
1275 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276 numericCommonNameValue, sizeof(numericCommonNameValue) },
1277 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278 printableCommonNameValue, sizeof(printableCommonNameValue) },
1279 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280 t61CommonNameValue, sizeof(t61CommonNameValue) },
1281 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1283 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1285 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1287 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1288 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1289 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1290 generalCommonNameValue, sizeof(generalCommonNameValue) },
1291 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1292 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1293 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1294 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1295 /* The following tests succeed under Windows, but really should fail,
1296 * they contain characters that are illegal for the encoding. I'm
1297 * including them to justify my lazy encoding.
1299 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1300 sizeof(bin42) },
1301 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1302 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1303 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1304 bin44, sizeof(bin44) },
1306 /* This is kept separate, because the decoding doesn't return to the original
1307 * value.
1309 static struct EncodedNameValue embeddedNullNameValue = {
1310 { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1311 ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1313 static void test_encodeNameValue(DWORD dwEncoding)
1315 BYTE *buf = NULL;
1316 DWORD size = 0, i;
1317 BOOL ret;
1318 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1320 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1321 value.Value.pbData = printableCommonNameValue;
1322 value.Value.cbData = sizeof(printableCommonNameValue);
1323 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1324 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1325 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1326 if (ret)
1328 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1329 size);
1330 ok(!memcmp(buf, printableCommonNameValue, size),
1331 "Unexpected encoding\n");
1332 LocalFree(buf);
1334 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1336 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1337 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1338 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1339 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1340 nameValues[i].value.dwValueType, GetLastError());
1341 if (ret)
1343 ok(size == nameValues[i].encodedSize,
1344 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1345 ok(!memcmp(buf, nameValues[i].encoded, size),
1346 "Got unexpected encoding\n");
1347 LocalFree(buf);
1350 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1351 &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1352 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1353 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1354 embeddedNullNameValue.value.dwValueType, GetLastError());
1355 if (ret)
1357 ok(size == embeddedNullNameValue.encodedSize,
1358 "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1359 ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1360 "Got unexpected encoding\n");
1361 LocalFree(buf);
1365 static void test_decodeNameValue(DWORD dwEncoding)
1367 int i;
1368 BYTE *buf = NULL;
1369 DWORD bufSize = 0;
1370 BOOL ret;
1372 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1374 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1375 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1376 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1377 &buf, &bufSize);
1378 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1379 nameValues[i].value.dwValueType, GetLastError());
1380 if (ret)
1382 compareNameValues(&nameValues[i].value,
1383 (const CERT_NAME_VALUE *)buf);
1384 LocalFree(buf);
1387 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1388 embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1389 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1390 &buf, &bufSize);
1391 /* Some Windows versions disallow name values with embedded NULLs, so
1392 * either success or failure is acceptable.
1394 if (ret)
1396 CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1397 { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1398 CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1399 { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1400 const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1401 *expected = NULL;
1403 /* Some Windows versions decode name values with embedded NULLs,
1404 * others leave them encoded, even with the same version of crypt32.
1405 * Accept either.
1407 ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1408 got->dwValueType == CERT_RDN_IA5_STRING,
1409 "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1410 got->dwValueType);
1411 if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1412 expected = &rdnEncodedValue;
1413 else if (got->dwValueType == CERT_RDN_IA5_STRING)
1414 expected = &embeddedNullValue;
1415 if (expected)
1417 ok(got->Value.cbData == expected->Value.cbData,
1418 "String type %d: unexpected data size, got %d, expected %d\n",
1419 got->dwValueType, got->Value.cbData, expected->Value.cbData);
1420 if (got->Value.cbData && got->Value.pbData)
1421 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1422 min(got->Value.cbData, expected->Value.cbData)),
1423 "String type %d: unexpected value\n", expected->dwValueType);
1425 LocalFree(buf);
1429 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1430 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1431 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1432 'h','q','.','o','r','g',0 };
1433 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1434 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1435 0x6f, 0x72, 0x67 };
1436 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1437 0x575b, 0 };
1438 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1439 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1440 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1441 static const BYTE localhost[] = { 127, 0, 0, 1 };
1442 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1443 0x01 };
1444 static const unsigned char encodedCommonName[] = {
1445 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1446 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1447 static const BYTE encodedDirectoryName[] = {
1448 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1449 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1451 static void test_encodeAltName(DWORD dwEncoding)
1453 CERT_ALT_NAME_INFO info = { 0 };
1454 CERT_ALT_NAME_ENTRY entry = { 0 };
1455 BYTE *buf = NULL;
1456 DWORD size = 0;
1457 BOOL ret;
1458 char oid[] = "1.2.3";
1460 /* Test with empty info */
1461 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1462 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1463 if (ret)
1465 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1466 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1467 LocalFree(buf);
1469 /* Test with an empty entry */
1470 info.cAltEntry = 1;
1471 info.rgAltEntry = &entry;
1472 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1473 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1474 ok(!ret && GetLastError() == E_INVALIDARG,
1475 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1476 /* Test with an empty pointer */
1477 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1478 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1479 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1480 if (ret)
1482 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1483 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1484 LocalFree(buf);
1486 /* Test with a real URL */
1487 U(entry).pwszURL = (LPWSTR)url;
1488 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1489 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1490 if (ret)
1492 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1493 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1494 LocalFree(buf);
1496 /* Now with the URL containing an invalid IA5 char */
1497 U(entry).pwszURL = (LPWSTR)nihongoURL;
1498 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1499 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1500 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1501 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1502 /* The first invalid character is at index 7 */
1503 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1504 "Expected invalid char at index 7, got %d\n",
1505 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1506 /* Now with the URL missing a scheme */
1507 U(entry).pwszURL = (LPWSTR)dnsName;
1508 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1509 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1510 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1511 if (ret)
1513 /* This succeeds, but it shouldn't, so don't worry about conforming */
1514 LocalFree(buf);
1516 /* Now with a DNS name */
1517 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1518 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1519 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1520 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1521 if (ret)
1523 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1524 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1525 LocalFree(buf);
1527 /* Test with an IP address */
1528 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1529 U(entry).IPAddress.cbData = sizeof(localhost);
1530 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1531 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1532 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1533 if (ret)
1535 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1536 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1537 LocalFree(buf);
1539 /* Test with OID */
1540 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1541 U(entry).pszRegisteredID = oid;
1542 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1543 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1544 if (ret)
1546 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1547 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1548 LocalFree(buf);
1550 /* Test with directory name */
1551 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1552 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1553 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1554 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1555 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1556 if (ret)
1558 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1559 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1560 LocalFree(buf);
1564 static void test_decodeAltName(DWORD dwEncoding)
1566 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1567 0x00, 0x00, 0x01 };
1568 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1569 0x01 };
1570 static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1571 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1572 static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1573 0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1574 static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1575 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1576 BOOL ret;
1577 BYTE *buf = NULL;
1578 DWORD bufSize = 0;
1579 CERT_ALT_NAME_INFO *info;
1581 /* Test some bogus ones first */
1582 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1583 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1584 NULL, &buf, &bufSize);
1585 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1586 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1587 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1588 GetLastError());
1589 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1590 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1591 &bufSize);
1592 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1593 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1594 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1595 GetLastError());
1596 /* Now expected cases */
1597 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1598 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1599 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1600 if (ret)
1602 info = (CERT_ALT_NAME_INFO *)buf;
1604 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1605 info->cAltEntry);
1606 LocalFree(buf);
1608 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1609 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611 if (ret)
1613 info = (CERT_ALT_NAME_INFO *)buf;
1615 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616 info->cAltEntry);
1617 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1618 "Expected CERT_ALT_NAME_URL, got %d\n",
1619 info->rgAltEntry[0].dwAltNameChoice);
1620 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1621 "Expected empty URL\n");
1622 LocalFree(buf);
1624 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1626 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1627 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1628 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1629 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1630 if (ret)
1632 info = (CERT_ALT_NAME_INFO *)buf;
1634 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1635 info->cAltEntry);
1636 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1637 "Expected CERT_ALT_NAME_URL, got %d\n",
1638 info->rgAltEntry[0].dwAltNameChoice);
1639 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1640 LocalFree(buf);
1642 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1643 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1644 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1645 if (ret)
1647 info = (CERT_ALT_NAME_INFO *)buf;
1649 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1650 info->cAltEntry);
1651 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1652 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1653 info->rgAltEntry[0].dwAltNameChoice);
1654 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1655 "Unexpected DNS name\n");
1656 LocalFree(buf);
1658 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1659 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1660 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1661 if (ret)
1663 info = (CERT_ALT_NAME_INFO *)buf;
1665 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1666 info->cAltEntry);
1667 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1668 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1669 info->rgAltEntry[0].dwAltNameChoice);
1670 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1671 "Unexpected IP address length %d\n",
1672 U(info->rgAltEntry[0]).IPAddress.cbData);
1673 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1674 sizeof(localhost)), "Unexpected IP address value\n");
1675 LocalFree(buf);
1677 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1678 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1679 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1680 if (ret)
1682 info = (CERT_ALT_NAME_INFO *)buf;
1684 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1685 info->cAltEntry);
1686 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1687 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1688 info->rgAltEntry[0].dwAltNameChoice);
1689 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1690 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1691 LocalFree(buf);
1693 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1694 encodedDirectoryName, sizeof(encodedDirectoryName),
1695 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1696 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1697 if (ret)
1699 info = (CERT_ALT_NAME_INFO *)buf;
1701 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1702 info->cAltEntry);
1703 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1704 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1705 info->rgAltEntry[0].dwAltNameChoice);
1706 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1707 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1708 U(info->rgAltEntry[0]).DirectoryName.cbData);
1709 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1710 encodedCommonName, sizeof(encodedCommonName)),
1711 "Unexpected directory name value\n");
1712 LocalFree(buf);
1714 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1715 dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1716 NULL, &buf, &bufSize);
1717 /* Fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned about the
1718 * particular failure, just that it doesn't decode.
1719 * It succeeds on (broken) Windows versions that haven't addressed
1720 * embedded NULLs in alternate names.
1722 ok(!ret || broken(ret), "expected failure\n");
1723 /* An embedded bell character is allowed, however. */
1724 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1725 dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1726 NULL, &buf, &bufSize);
1727 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1728 if (ret)
1730 info = (CERT_ALT_NAME_INFO *)buf;
1732 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1733 info->cAltEntry);
1734 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1735 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1736 info->rgAltEntry[0].dwAltNameChoice);
1737 LocalFree(buf);
1739 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1740 url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1741 NULL, &buf, &bufSize);
1742 /* Again, fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned
1743 * about the particular failure, just that it doesn't decode.
1744 * It succeeds on (broken) Windows versions that haven't addressed
1745 * embedded NULLs in alternate names.
1747 ok(!ret || broken(ret), "expected failure\n");
1750 struct UnicodeExpectedError
1752 DWORD valueType;
1753 LPCWSTR str;
1754 DWORD errorIndex;
1755 DWORD error;
1758 static const WCHAR oneW[] = { '1',0 };
1759 static const WCHAR aW[] = { 'a',0 };
1760 static const WCHAR quoteW[] = { '"', 0 };
1762 static struct UnicodeExpectedError unicodeErrors[] = {
1763 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1764 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1765 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1766 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1767 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1768 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1771 struct UnicodeExpectedResult
1773 DWORD valueType;
1774 LPCWSTR str;
1775 CRYPT_DATA_BLOB encoded;
1778 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1779 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1780 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1781 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1782 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1783 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1784 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1785 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1786 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1787 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1788 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1789 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1790 0x5b };
1791 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1792 0x6f,0x5b };
1793 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1794 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1795 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1796 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1798 static struct UnicodeExpectedResult unicodeResults[] = {
1799 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1800 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1801 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1802 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1803 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1804 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1805 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1806 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1807 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1808 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1809 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1810 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1811 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1814 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1815 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1816 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1819 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1821 BYTE *buf = NULL;
1822 DWORD size = 0, i;
1823 BOOL ret;
1824 CERT_NAME_VALUE value;
1826 if (0)
1828 /* Crashes on win9x */
1829 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1830 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1831 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1832 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1834 /* Have to have a string of some sort */
1835 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1836 value.Value.pbData = NULL;
1837 value.Value.cbData = 0;
1838 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1839 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1840 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1841 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1842 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1843 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1844 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1845 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1846 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1847 value.dwValueType = CERT_RDN_ANY_TYPE;
1848 value.Value.pbData = (LPBYTE)oneW;
1849 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1850 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1851 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1852 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1853 value.Value.cbData = sizeof(oneW);
1854 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1855 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1856 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1857 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1858 /* An encoded string with specified length isn't good enough either */
1859 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1860 value.Value.pbData = oneUniversal;
1861 value.Value.cbData = sizeof(oneUniversal);
1862 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1863 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1864 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1865 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1866 /* More failure checking */
1867 value.Value.cbData = 0;
1868 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1870 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1871 value.dwValueType = unicodeErrors[i].valueType;
1872 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1873 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1874 ok(!ret && GetLastError() == unicodeErrors[i].error,
1875 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1876 unicodeErrors[i].error, GetLastError());
1877 ok(size == unicodeErrors[i].errorIndex,
1878 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1879 size);
1881 /* cbData can be zero if the string is NULL-terminated */
1882 value.Value.cbData = 0;
1883 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1885 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1886 value.dwValueType = unicodeResults[i].valueType;
1887 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1888 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1889 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1890 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1891 if (ret)
1893 ok(size == unicodeResults[i].encoded.cbData,
1894 "Value type %d: expected size %d, got %d\n",
1895 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1896 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1897 "Value type %d: unexpected value\n", value.dwValueType);
1898 LocalFree(buf);
1901 /* These "encode," but they do so by truncating each unicode character
1902 * rather than properly encoding it. Kept separate from the proper results,
1903 * because the encoded forms won't decode to their original strings.
1905 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1907 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1908 value.dwValueType = unicodeWeirdness[i].valueType;
1909 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1910 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1911 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1912 if (ret)
1914 ok(size == unicodeWeirdness[i].encoded.cbData,
1915 "Value type %d: expected size %d, got %d\n",
1916 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1917 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1918 "Value type %d: unexpected value\n", value.dwValueType);
1919 LocalFree(buf);
1924 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1926 if (n <= 0) return 0;
1927 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1928 return *str1 - *str2;
1931 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1933 DWORD i;
1935 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1937 BYTE *buf = NULL;
1938 BOOL ret;
1939 DWORD size = 0;
1941 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1942 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1943 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1944 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1945 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1946 if (ret && buf)
1948 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1950 ok(value->dwValueType == unicodeResults[i].valueType,
1951 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1952 value->dwValueType);
1953 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1954 value->Value.cbData / sizeof(WCHAR)),
1955 "Unexpected decoded value for index %d (value type %d)\n", i,
1956 unicodeResults[i].valueType);
1957 LocalFree(buf);
1962 struct encodedOctets
1964 const BYTE *val;
1965 const BYTE *encoded;
1968 static const unsigned char bin46[] = { 'h','i',0 };
1969 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1970 static const unsigned char bin48[] = {
1971 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1972 static const unsigned char bin49[] = {
1973 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1974 static const unsigned char bin50[] = { 0 };
1975 static const unsigned char bin51[] = { 0x04,0x00,0 };
1977 static const struct encodedOctets octets[] = {
1978 { bin46, bin47 },
1979 { bin48, bin49 },
1980 { bin50, bin51 },
1983 static void test_encodeOctets(DWORD dwEncoding)
1985 CRYPT_DATA_BLOB blob;
1986 DWORD i;
1988 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1990 BYTE *buf = NULL;
1991 BOOL ret;
1992 DWORD bufSize = 0;
1994 blob.cbData = strlen((const char*)octets[i].val);
1995 blob.pbData = (BYTE*)octets[i].val;
1996 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1997 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1998 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1999 if (ret)
2001 ok(buf[0] == 4,
2002 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2003 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2004 buf[1], octets[i].encoded[1]);
2005 ok(!memcmp(buf + 1, octets[i].encoded + 1,
2006 octets[i].encoded[1] + 1), "Got unexpected value\n");
2007 LocalFree(buf);
2012 static void test_decodeOctets(DWORD dwEncoding)
2014 DWORD i;
2016 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2018 BYTE *buf = NULL;
2019 BOOL ret;
2020 DWORD bufSize = 0;
2022 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2023 octets[i].encoded, octets[i].encoded[1] + 2,
2024 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2025 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2026 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2027 "Expected size >= %d, got %d\n",
2028 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2029 ok(buf != NULL, "Expected allocated buffer\n");
2030 if (ret)
2032 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2034 if (blob->cbData)
2035 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2036 "Unexpected value\n");
2037 LocalFree(buf);
2042 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2044 struct encodedBits
2046 DWORD cUnusedBits;
2047 const BYTE *encoded;
2048 DWORD cbDecoded;
2049 const BYTE *decoded;
2052 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2053 static const unsigned char bin53[] = { 0xff,0xff };
2054 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2055 static const unsigned char bin55[] = { 0xff,0xfe };
2056 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2057 static const unsigned char bin57[] = { 0xfe };
2058 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2060 static const struct encodedBits bits[] = {
2061 /* normal test cases */
2062 { 0, bin52, 2, bin53 },
2063 { 1, bin54, 2, bin55 },
2064 /* strange test case, showing cUnusedBits >= 8 is allowed */
2065 { 9, bin56, 1, bin57 },
2068 static void test_encodeBits(DWORD dwEncoding)
2070 DWORD i;
2072 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2074 CRYPT_BIT_BLOB blob;
2075 BOOL ret;
2076 BYTE *buf = NULL;
2077 DWORD bufSize = 0;
2079 blob.cbData = sizeof(bytesToEncode);
2080 blob.pbData = (BYTE *)bytesToEncode;
2081 blob.cUnusedBits = bits[i].cUnusedBits;
2082 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2083 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2084 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2085 if (ret)
2087 ok(bufSize == bits[i].encoded[1] + 2,
2088 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2089 bits[i].encoded[1] + 2);
2090 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2091 "%d: Unexpected value\n", i);
2092 LocalFree(buf);
2097 static void test_decodeBits(DWORD dwEncoding)
2099 static const BYTE ber[] = "\x03\x02\x01\xff";
2100 static const BYTE berDecoded = 0xfe;
2101 DWORD i;
2102 BOOL ret;
2103 BYTE *buf = NULL;
2104 DWORD bufSize = 0;
2106 /* normal cases */
2107 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2109 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2110 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2111 &bufSize);
2112 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2113 if (ret)
2115 CRYPT_BIT_BLOB *blob;
2117 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2118 "Got unexpected size %d\n", bufSize);
2119 blob = (CRYPT_BIT_BLOB *)buf;
2120 ok(blob->cbData == bits[i].cbDecoded,
2121 "Got unexpected length %d, expected %d\n", blob->cbData,
2122 bits[i].cbDecoded);
2123 if (blob->cbData && bits[i].cbDecoded)
2124 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2125 "Unexpected value\n");
2126 LocalFree(buf);
2129 /* special case: check that something that's valid in BER but not in DER
2130 * decodes successfully
2132 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2133 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2134 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2135 if (ret)
2137 CRYPT_BIT_BLOB *blob;
2139 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2140 "Got unexpected size %d\n", bufSize);
2141 blob = (CRYPT_BIT_BLOB *)buf;
2142 ok(blob->cbData == sizeof(berDecoded),
2143 "Got unexpected length %d\n", blob->cbData);
2144 if (blob->cbData)
2145 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2146 LocalFree(buf);
2150 struct Constraints2
2152 CERT_BASIC_CONSTRAINTS2_INFO info;
2153 const BYTE *encoded;
2156 static const unsigned char bin59[] = { 0x30,0x00 };
2157 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2158 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2159 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2160 static const struct Constraints2 constraints2[] = {
2161 /* empty constraints */
2162 { { FALSE, FALSE, 0}, bin59 },
2163 /* can be a CA */
2164 { { TRUE, FALSE, 0}, bin60 },
2165 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2166 * but that's not the case
2168 { { FALSE, TRUE, 0}, bin61 },
2169 /* can be a CA and has path length constraints set */
2170 { { TRUE, TRUE, 1}, bin62 },
2173 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2174 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2175 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2176 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2177 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2178 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2179 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2180 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2181 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2182 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2184 static void test_encodeBasicConstraints(DWORD dwEncoding)
2186 DWORD i, bufSize = 0;
2187 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2188 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2189 (LPBYTE)encodedDomainName };
2190 BOOL ret;
2191 BYTE *buf = NULL;
2193 /* First test with the simpler info2 */
2194 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2196 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2197 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2198 &bufSize);
2199 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2200 if (ret)
2202 ok(bufSize == constraints2[i].encoded[1] + 2,
2203 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2204 bufSize);
2205 ok(!memcmp(buf, constraints2[i].encoded,
2206 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2207 LocalFree(buf);
2210 /* Now test with more complex basic constraints */
2211 info.SubjectType.cbData = 0;
2212 info.fPathLenConstraint = FALSE;
2213 info.cSubtreesConstraint = 0;
2214 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2215 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2216 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2217 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2218 if (ret)
2220 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2221 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2222 "Unexpected value\n");
2223 LocalFree(buf);
2225 /* None of the certs I examined had any subtree constraint, but I test one
2226 * anyway just in case.
2228 info.cSubtreesConstraint = 1;
2229 info.rgSubtreesConstraint = &nameBlob;
2230 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2231 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2232 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2233 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2234 if (ret)
2236 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2237 ok(!memcmp(buf, constraintWithDomainName,
2238 sizeof(constraintWithDomainName)), "Unexpected value\n");
2239 LocalFree(buf);
2241 /* FIXME: test encoding with subject type. */
2244 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2246 static void test_decodeBasicConstraints(DWORD dwEncoding)
2248 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2249 0xff };
2250 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2251 DWORD i;
2252 BOOL ret;
2253 BYTE *buf = NULL;
2254 DWORD bufSize = 0;
2256 /* First test with simpler info2 */
2257 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2259 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2260 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2261 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2262 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2263 GetLastError());
2264 if (ret)
2266 CERT_BASIC_CONSTRAINTS2_INFO *info =
2267 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2269 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2270 "Unexpected value for item %d\n", i);
2271 LocalFree(buf);
2274 /* Check with the order of encoded elements inverted */
2275 buf = (PBYTE)1;
2276 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2277 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2278 &bufSize);
2279 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2280 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2281 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2282 GetLastError());
2283 ok(!buf, "Expected buf to be set to NULL\n");
2284 /* Check with a non-DER bool */
2285 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2286 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2287 &buf, &bufSize);
2288 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2289 if (ret)
2291 CERT_BASIC_CONSTRAINTS2_INFO *info =
2292 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2294 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2295 LocalFree(buf);
2297 /* Check with a non-basic constraints value */
2298 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2299 encodedCommonName, encodedCommonName[1] + 2,
2300 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2301 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2302 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2303 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2304 GetLastError());
2305 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2306 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2307 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2308 &buf, &bufSize);
2309 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2310 if (ret)
2312 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2314 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2315 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2316 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2317 LocalFree(buf);
2319 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2320 constraintWithDomainName, sizeof(constraintWithDomainName),
2321 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2322 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2323 if (ret)
2325 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2327 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2328 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2329 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2330 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2332 ok(info->rgSubtreesConstraint[0].cbData ==
2333 sizeof(encodedDomainName), "Wrong size %d\n",
2334 info->rgSubtreesConstraint[0].cbData);
2335 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2336 sizeof(encodedDomainName)), "Unexpected value\n");
2338 LocalFree(buf);
2342 /* These are terrible public keys of course, I'm just testing encoding */
2343 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2344 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2345 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2346 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2347 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2349 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2350 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2352 struct EncodedRSAPubKey
2354 const BYTE *modulus;
2355 size_t modulusLen;
2356 const BYTE *encoded;
2357 size_t decodedModulusLen;
2360 static const struct EncodedRSAPubKey rsaPubKeys[] = {
2361 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2362 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2363 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2364 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2367 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2369 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2370 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2371 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2372 BOOL ret;
2373 BYTE *buf = NULL;
2374 DWORD bufSize = 0, i;
2376 /* Try with a bogus blob type */
2377 hdr->bType = 2;
2378 hdr->bVersion = CUR_BLOB_VERSION;
2379 hdr->reserved = 0;
2380 hdr->aiKeyAlg = CALG_RSA_KEYX;
2381 rsaPubKey->magic = 0x31415352;
2382 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2383 rsaPubKey->pubexp = 65537;
2384 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2385 sizeof(modulus1));
2387 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2388 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2389 ok(!ret && GetLastError() == E_INVALIDARG,
2390 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2391 /* Now with a bogus reserved field */
2392 hdr->bType = PUBLICKEYBLOB;
2393 hdr->reserved = 1;
2394 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2395 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2396 if (ret)
2398 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2399 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2400 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2401 LocalFree(buf);
2403 /* Now with a bogus blob version */
2404 hdr->reserved = 0;
2405 hdr->bVersion = 0;
2406 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2407 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2408 if (ret)
2410 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2411 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2412 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2413 LocalFree(buf);
2415 /* And with a bogus alg ID */
2416 hdr->bVersion = CUR_BLOB_VERSION;
2417 hdr->aiKeyAlg = CALG_DES;
2418 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2419 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2420 if (ret)
2422 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2423 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2424 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2425 LocalFree(buf);
2427 /* Check a couple of RSA-related OIDs */
2428 hdr->aiKeyAlg = CALG_RSA_KEYX;
2429 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2430 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2431 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2432 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2433 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2434 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2435 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2436 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2437 /* Finally, all valid */
2438 hdr->aiKeyAlg = CALG_RSA_KEYX;
2439 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2441 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2442 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2443 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2444 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2445 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2446 if (ret)
2448 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2449 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2450 bufSize);
2451 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2452 "Unexpected value\n");
2453 LocalFree(buf);
2458 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2460 DWORD i;
2461 LPBYTE buf = NULL;
2462 DWORD bufSize = 0;
2463 BOOL ret;
2465 /* Try with a bad length */
2466 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2467 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2468 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2469 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2470 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2471 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2472 GetLastError());
2473 /* Try with a couple of RSA-related OIDs */
2474 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2475 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2476 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2477 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2478 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2479 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2480 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2481 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2482 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2483 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2484 /* Now try success cases */
2485 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2487 bufSize = 0;
2488 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2489 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2490 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2491 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2492 if (ret)
2494 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2495 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2497 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2498 rsaPubKeys[i].decodedModulusLen,
2499 "Wrong size %d\n", bufSize);
2500 ok(hdr->bType == PUBLICKEYBLOB,
2501 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2502 hdr->bType);
2503 ok(hdr->bVersion == CUR_BLOB_VERSION,
2504 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2505 CUR_BLOB_VERSION, hdr->bVersion);
2506 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2507 hdr->reserved);
2508 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2509 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2510 ok(rsaPubKey->magic == 0x31415352,
2511 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2512 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2513 "Wrong bit len %d\n", rsaPubKey->bitlen);
2514 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2515 rsaPubKey->pubexp);
2516 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2517 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2518 "Unexpected modulus\n");
2519 LocalFree(buf);
2524 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2525 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2526 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2528 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2529 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2530 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2531 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2533 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2535 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2536 CRYPT_SEQUENCE_OF_ANY seq;
2537 DWORD i;
2538 BOOL ret;
2539 BYTE *buf = NULL;
2540 DWORD bufSize = 0;
2542 /* Encode a homogeneous sequence */
2543 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2545 blobs[i].cbData = ints[i].encoded[1] + 2;
2546 blobs[i].pbData = (BYTE *)ints[i].encoded;
2548 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2549 seq.rgValue = blobs;
2551 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2552 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2553 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2554 if (ret)
2556 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2557 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2558 LocalFree(buf);
2560 /* Change the type of the first element in the sequence, and give it
2561 * another go
2563 blobs[0].cbData = times[0].encodedTime[1] + 2;
2564 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2565 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2566 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2567 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2568 if (ret)
2570 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2571 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2572 "Unexpected value\n");
2573 LocalFree(buf);
2577 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2579 BOOL ret;
2580 BYTE *buf = NULL;
2581 DWORD bufSize = 0;
2583 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2584 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2585 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2586 if (ret)
2588 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2589 DWORD i;
2591 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2592 "Wrong elements %d\n", seq->cValue);
2593 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2595 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2596 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2597 seq->rgValue[i].cbData);
2598 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2599 ints[i].encoded[1] + 2), "Unexpected value\n");
2601 LocalFree(buf);
2603 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2604 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2605 &bufSize);
2606 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2607 if (ret)
2609 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2611 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2612 "Wrong elements %d\n", seq->cValue);
2613 /* Just check the first element since it's all that changed */
2614 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2615 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2616 seq->rgValue[0].cbData);
2617 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2618 times[0].encodedTime[1] + 2), "Unexpected value\n");
2619 LocalFree(buf);
2623 struct encodedExtensions
2625 CERT_EXTENSIONS exts;
2626 const BYTE *encoded;
2629 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2630 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2631 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2632 static CERT_EXTENSION criticalExt =
2633 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2634 static CERT_EXTENSION nonCriticalExt =
2635 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2636 static CHAR oid_short[] = "1.1";
2637 static CERT_EXTENSION extWithShortOid =
2638 { oid_short, FALSE, { 0, NULL } };
2640 static const BYTE ext0[] = { 0x30,0x00 };
2641 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2642 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2643 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2644 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2645 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2647 static const struct encodedExtensions exts[] = {
2648 { { 0, NULL }, ext0 },
2649 { { 1, &criticalExt }, ext1 },
2650 { { 1, &nonCriticalExt }, ext2 },
2651 { { 1, &extWithShortOid }, ext3 }
2654 static void test_encodeExtensions(DWORD dwEncoding)
2656 DWORD i;
2658 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2660 BOOL ret;
2661 BYTE *buf = NULL;
2662 DWORD bufSize = 0;
2664 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2665 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2666 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2667 if (ret)
2669 ok(bufSize == exts[i].encoded[1] + 2,
2670 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2671 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2672 "Unexpected value\n");
2673 LocalFree(buf);
2678 static void test_decodeExtensions(DWORD dwEncoding)
2680 DWORD i;
2682 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2684 BOOL ret;
2685 BYTE *buf = NULL;
2686 DWORD bufSize = 0;
2688 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2689 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2690 NULL, &buf, &bufSize);
2691 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2692 if (ret)
2694 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2695 DWORD j;
2697 ok(ext->cExtension == exts[i].exts.cExtension,
2698 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2699 ext->cExtension);
2700 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2702 ok(!strcmp(ext->rgExtension[j].pszObjId,
2703 exts[i].exts.rgExtension[j].pszObjId),
2704 "Expected OID %s, got %s\n",
2705 exts[i].exts.rgExtension[j].pszObjId,
2706 ext->rgExtension[j].pszObjId);
2707 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2708 exts[i].exts.rgExtension[j].Value.pbData,
2709 exts[i].exts.rgExtension[j].Value.cbData),
2710 "Unexpected value\n");
2712 LocalFree(buf);
2714 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2715 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2716 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2717 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2718 if (buf)
2720 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2721 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2722 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2723 HeapFree(GetProcessHeap(), 0, buf);
2728 /* MS encodes public key info with a NULL if the algorithm identifier's
2729 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2730 * it encodes them by omitting the algorithm parameters. It accepts either
2731 * form for decoding.
2733 struct encodedPublicKey
2735 CERT_PUBLIC_KEY_INFO info;
2736 const BYTE *encoded;
2737 const BYTE *encodedNoNull;
2738 CERT_PUBLIC_KEY_INFO decoded;
2741 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2742 0xe, 0xf };
2743 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2745 static const unsigned char bin64[] = {
2746 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2747 static const unsigned char bin65[] = {
2748 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2749 static const unsigned char bin66[] = {
2750 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2751 static const unsigned char bin67[] = {
2752 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2753 static const unsigned char bin68[] = {
2754 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2755 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2756 static const unsigned char bin69[] = {
2757 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2758 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2759 static const unsigned char bin70[] = {
2760 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2761 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2762 0x0f};
2763 static const unsigned char bin71[] = {
2764 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2765 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2766 0x0f};
2767 static unsigned char bin72[] = { 0x05,0x00};
2769 static CHAR oid_bogus[] = "1.2.3",
2770 oid_rsa[] = szOID_RSA;
2772 static const struct encodedPublicKey pubKeys[] = {
2773 /* with a bogus OID */
2774 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2775 bin64, bin65,
2776 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2777 /* some normal keys */
2778 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2779 bin66, bin67,
2780 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2781 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2782 bin68, bin69,
2783 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2784 /* with add'l parameters--note they must be DER-encoded */
2785 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2786 (BYTE *)aKey, 0 } },
2787 bin70, bin71,
2788 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2789 (BYTE *)aKey, 0 } } },
2792 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2794 DWORD i;
2796 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2798 BOOL ret;
2799 BYTE *buf = NULL;
2800 DWORD bufSize = 0;
2802 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2803 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2804 &bufSize);
2805 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2806 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2807 if (ret)
2809 ok(bufSize == pubKeys[i].encoded[1] + 2,
2810 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2811 if (bufSize == pubKeys[i].encoded[1] + 2)
2812 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2813 "Unexpected value\n");
2814 LocalFree(buf);
2819 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2820 const CERT_PUBLIC_KEY_INFO *got)
2822 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2823 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2824 got->Algorithm.pszObjId);
2825 ok(expected->Algorithm.Parameters.cbData ==
2826 got->Algorithm.Parameters.cbData,
2827 "Expected parameters of %d bytes, got %d\n",
2828 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2829 if (expected->Algorithm.Parameters.cbData)
2830 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2831 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2832 "Unexpected algorithm parameters\n");
2833 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2834 "Expected public key of %d bytes, got %d\n",
2835 expected->PublicKey.cbData, got->PublicKey.cbData);
2836 if (expected->PublicKey.cbData)
2837 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2838 got->PublicKey.cbData), "Unexpected public key value\n");
2841 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2843 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2844 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2845 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2846 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2847 DWORD i;
2848 BOOL ret;
2849 BYTE *buf = NULL;
2850 DWORD bufSize = 0;
2852 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2854 /* The NULL form decodes to the decoded member */
2855 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2856 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2857 NULL, &buf, &bufSize);
2858 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2859 if (ret)
2861 comparePublicKeyInfo(&pubKeys[i].decoded,
2862 (CERT_PUBLIC_KEY_INFO *)buf);
2863 LocalFree(buf);
2865 /* The non-NULL form decodes to the original */
2866 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2867 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2868 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2869 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2870 if (ret)
2872 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2873 LocalFree(buf);
2876 /* Test with bogus (not valid DER) parameters */
2877 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2878 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2879 NULL, &buf, &bufSize);
2880 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2881 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2882 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2883 GetLastError());
2886 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2887 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2888 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2889 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2890 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2891 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2892 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2893 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2894 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2895 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2896 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2897 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2898 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2899 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2900 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2901 static const BYTE v4Cert[] = {
2902 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2903 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2904 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2905 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2906 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2907 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2908 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2909 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2910 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2911 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2912 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2913 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2914 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2915 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2916 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2917 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2918 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2919 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2920 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2921 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2922 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2923 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2924 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2925 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2926 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2927 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2928 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2929 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2930 static const BYTE v1CertWithPubKey[] = {
2931 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2932 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2933 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2934 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2935 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2936 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2937 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2938 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2939 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2940 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2941 0x01,0x01 };
2942 static const BYTE v1CertWithPubKeyNoNull[] = {
2943 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2944 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2945 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2946 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2947 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2948 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2949 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2950 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2951 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2952 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2953 static const BYTE v1CertWithSubjectKeyId[] = {
2954 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2955 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2956 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2957 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2958 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2959 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2960 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2961 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2962 0x4c,0x61,0x6e,0x67,0x00 };
2963 static const BYTE v1CertWithIssuerUniqueId[] = {
2964 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2965 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2966 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2967 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2968 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2969 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2970 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2971 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2972 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2973 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2974 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2975 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2976 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2977 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2978 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2979 0x01,0x01,0xff,0x02,0x01,0x01 };
2980 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2981 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2982 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2983 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2984 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2985 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2986 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2987 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2988 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2989 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2990 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2991 0xff,0x02,0x01,0x01 };
2993 static const BYTE serialNum[] = { 0x01 };
2995 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2997 BOOL ret;
2998 BYTE *buf = NULL;
2999 DWORD size = 0;
3000 CERT_INFO info = { 0 };
3001 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3002 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
3003 CERT_EXTENSION ext;
3005 if (0)
3007 /* Test with NULL pvStructInfo (crashes on win9x) */
3008 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3009 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3010 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3011 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3013 /* Test with a V1 cert */
3014 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3015 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3016 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3017 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3018 if (ret)
3020 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3021 v1Cert[1] + 2, size);
3022 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3023 LocalFree(buf);
3025 /* Test v2 cert */
3026 info.dwVersion = CERT_V2;
3027 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3028 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3029 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3030 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3031 if (ret)
3033 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3034 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3035 LocalFree(buf);
3037 /* Test v3 cert */
3038 info.dwVersion = CERT_V3;
3039 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3040 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3041 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3042 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3043 if (ret)
3045 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3046 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3047 LocalFree(buf);
3049 /* A v4 cert? */
3050 info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3051 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3052 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3053 if (ret)
3055 ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3056 ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3057 LocalFree(buf);
3059 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3060 * API doesn't prevent it)
3062 info.dwVersion = CERT_V1;
3063 info.cExtension = 1;
3064 info.rgExtension = &criticalExt;
3065 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3066 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3067 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3068 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3069 if (ret)
3071 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3072 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3073 LocalFree(buf);
3075 /* test v1 cert with a serial number */
3076 info.SerialNumber.cbData = sizeof(serialNum);
3077 info.SerialNumber.pbData = (BYTE *)serialNum;
3078 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3079 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3080 if (ret)
3082 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3083 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3084 LocalFree(buf);
3086 /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3087 info.dwVersion = CERT_V1;
3088 info.cExtension = 0;
3089 info.IssuerUniqueId.cbData = sizeof(serialNum);
3090 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3091 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3092 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3093 ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3094 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3095 if (ret)
3097 ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3098 ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3099 "Got unexpected value\n");
3100 LocalFree(buf);
3102 /* Test v1 cert with an issuer name, a subject name, and a serial number */
3103 info.IssuerUniqueId.cbData = 0;
3104 info.IssuerUniqueId.pbData = NULL;
3105 info.cExtension = 1;
3106 info.rgExtension = &criticalExt;
3107 info.Issuer.cbData = sizeof(encodedCommonName);
3108 info.Issuer.pbData = (BYTE *)encodedCommonName;
3109 info.Subject.cbData = sizeof(encodedCommonName);
3110 info.Subject.pbData = (BYTE *)encodedCommonName;
3111 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3112 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3113 if (ret)
3115 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3116 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3117 LocalFree(buf);
3119 /* Add a public key */
3120 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3121 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3122 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3123 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3124 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3125 if (ret)
3127 ok(size == sizeof(v1CertWithPubKey) ||
3128 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3129 if (size == sizeof(v1CertWithPubKey))
3130 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3131 else if (size == sizeof(v1CertWithPubKeyNoNull))
3132 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3133 "Got unexpected value\n");
3134 LocalFree(buf);
3136 /* Again add an issuer unique id */
3137 info.IssuerUniqueId.cbData = sizeof(serialNum);
3138 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3139 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3140 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3141 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3142 if (ret)
3144 ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3145 size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3146 "Wrong size %d\n", size);
3147 if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3148 ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3149 size), "unexpected value\n");
3150 else if (size ==
3151 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3152 ok(!memcmp(buf,
3153 v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3154 "unexpected value\n");
3155 LocalFree(buf);
3157 /* Remove the public key, and add a subject key identifier extension */
3158 info.IssuerUniqueId.cbData = 0;
3159 info.IssuerUniqueId.pbData = NULL;
3160 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3161 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3162 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3163 ext.pszObjId = oid_subject_key_identifier;
3164 ext.fCritical = FALSE;
3165 ext.Value.cbData = sizeof(octetCommonNameValue);
3166 ext.Value.pbData = octetCommonNameValue;
3167 info.cExtension = 1;
3168 info.rgExtension = &ext;
3169 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3170 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3171 if (ret)
3173 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3174 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3175 LocalFree(buf);
3179 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3181 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3182 v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3183 BOOL ret;
3184 BYTE *buf = NULL;
3185 DWORD size = 0, i;
3187 /* Test with NULL pbEncoded */
3188 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3189 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3190 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3191 GetLastError() == OSS_BAD_ARG /* Win9x */),
3192 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3193 if (0)
3195 /* Crashes on win9x */
3196 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3197 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3198 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3199 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3201 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3202 * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3203 * serial number, an issuer, a subject, and a public key.
3205 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3207 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3208 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3209 &buf, &size);
3210 ok(!ret, "Expected failure\n");
3212 /* The following succeeds, even though v1 certs are not allowed to have
3213 * extensions.
3215 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3216 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3217 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3218 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3219 if (ret)
3221 CERT_INFO *info = (CERT_INFO *)buf;
3223 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3224 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3225 info->dwVersion);
3226 ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3227 info->cExtension);
3228 LocalFree(buf);
3230 /* The following also succeeds, even though V1 certs are not allowed to
3231 * have issuer unique ids.
3233 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3234 v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3235 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3236 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3237 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3238 if (ret)
3240 CERT_INFO *info = (CERT_INFO *)buf;
3242 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3243 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3244 info->dwVersion);
3245 ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3246 "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3247 ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3248 "unexpected issuer unique id value\n");
3249 LocalFree(buf);
3251 /* Now check with serial number, subject and issuer specified */
3252 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3253 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3254 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3255 if (ret)
3257 CERT_INFO *info = (CERT_INFO *)buf;
3259 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3260 ok(info->SerialNumber.cbData == 1,
3261 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3262 ok(*info->SerialNumber.pbData == *serialNum,
3263 "Expected serial number %d, got %d\n", *serialNum,
3264 *info->SerialNumber.pbData);
3265 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3266 "Wrong size %d\n", info->Issuer.cbData);
3267 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3268 "Unexpected issuer\n");
3269 ok(info->Subject.cbData == sizeof(encodedCommonName),
3270 "Wrong size %d\n", info->Subject.cbData);
3271 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3272 info->Subject.cbData), "Unexpected subject\n");
3273 LocalFree(buf);
3275 /* Check again with pub key specified */
3276 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3277 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3278 &buf, &size);
3279 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3280 if (ret)
3282 CERT_INFO *info = (CERT_INFO *)buf;
3284 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3285 ok(info->SerialNumber.cbData == 1,
3286 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3287 ok(*info->SerialNumber.pbData == *serialNum,
3288 "Expected serial number %d, got %d\n", *serialNum,
3289 *info->SerialNumber.pbData);
3290 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3291 "Wrong size %d\n", info->Issuer.cbData);
3292 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3293 "Unexpected issuer\n");
3294 ok(info->Subject.cbData == sizeof(encodedCommonName),
3295 "Wrong size %d\n", info->Subject.cbData);
3296 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3297 info->Subject.cbData), "Unexpected subject\n");
3298 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3299 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3300 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3301 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3302 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3303 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3304 sizeof(aKey)), "Unexpected public key\n");
3305 LocalFree(buf);
3309 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3310 0xe, 0xf };
3312 static const BYTE signedBigCert[] = {
3313 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3314 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3315 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3316 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3317 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3318 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3319 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3320 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3321 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3322 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3323 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3324 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3326 static void test_encodeCert(DWORD dwEncoding)
3328 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3329 * also that bigCert is a NULL-terminated string, so don't count its
3330 * last byte (otherwise the signed cert won't decode.)
3332 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3333 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3334 BOOL ret;
3335 BYTE *buf = NULL;
3336 DWORD bufSize = 0;
3338 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3339 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3340 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3341 if (ret)
3343 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3344 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3345 LocalFree(buf);
3349 static void test_decodeCert(DWORD dwEncoding)
3351 BOOL ret;
3352 BYTE *buf = NULL;
3353 DWORD size = 0;
3355 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3356 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3357 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3358 if (ret)
3360 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3362 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3363 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3364 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3365 "Unexpected cert\n");
3366 ok(info->Signature.cbData == sizeof(hash),
3367 "Wrong signature size %d\n", info->Signature.cbData);
3368 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3369 "Unexpected signature\n");
3370 LocalFree(buf);
3372 /* A signed cert decodes as a CERT_INFO too */
3373 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3374 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3375 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3376 if (ret)
3378 CERT_INFO *info = (CERT_INFO *)buf;
3380 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3381 ok(info->SerialNumber.cbData == 1,
3382 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3383 ok(*info->SerialNumber.pbData == *serialNum,
3384 "Expected serial number %d, got %d\n", *serialNum,
3385 *info->SerialNumber.pbData);
3386 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3387 "Wrong size %d\n", info->Issuer.cbData);
3388 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3389 "Unexpected issuer\n");
3390 ok(info->Subject.cbData == sizeof(encodedCommonName),
3391 "Wrong size %d\n", info->Subject.cbData);
3392 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3393 info->Subject.cbData), "Unexpected subject\n");
3394 LocalFree(buf);
3398 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3399 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3400 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3401 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3402 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3403 0x00, 0x03 };
3404 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3405 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3406 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3407 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3408 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3409 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3410 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3411 0x2e, 0x6f, 0x72, 0x67 };
3412 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3413 CRL_REASON_AFFILIATION_CHANGED;
3415 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3417 CRL_DIST_POINTS_INFO info = { 0 };
3418 CRL_DIST_POINT point = { { 0 } };
3419 CERT_ALT_NAME_ENTRY entry = { 0 };
3420 BOOL ret;
3421 BYTE *buf = NULL;
3422 DWORD size = 0;
3424 /* Test with an empty info */
3425 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3426 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3427 ok(!ret && GetLastError() == E_INVALIDARG,
3428 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3429 /* Test with one empty dist point */
3430 info.cDistPoint = 1;
3431 info.rgDistPoint = &point;
3432 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3433 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3434 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3435 if (ret)
3437 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3438 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3439 LocalFree(buf);
3441 /* A dist point with an invalid name */
3442 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3443 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3444 U(entry).pwszURL = (LPWSTR)nihongoURL;
3445 U(point.DistPointName).FullName.cAltEntry = 1;
3446 U(point.DistPointName).FullName.rgAltEntry = &entry;
3447 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3448 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3449 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3450 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3451 /* The first invalid character is at index 7 */
3452 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3453 "Expected invalid char at index 7, got %d\n",
3454 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3455 /* A dist point with (just) a valid name */
3456 U(entry).pwszURL = (LPWSTR)url;
3457 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3458 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3459 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3460 if (ret)
3462 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3463 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3464 LocalFree(buf);
3466 /* A dist point with (just) reason flags */
3467 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3468 point.ReasonFlags.cbData = sizeof(crlReason);
3469 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3470 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3471 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3472 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3473 if (ret)
3475 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3476 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3477 LocalFree(buf);
3479 /* A dist point with just an issuer */
3480 point.ReasonFlags.cbData = 0;
3481 point.CRLIssuer.cAltEntry = 1;
3482 point.CRLIssuer.rgAltEntry = &entry;
3483 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3484 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3485 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3486 if (ret)
3488 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3489 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3490 LocalFree(buf);
3492 /* A dist point with both a name and an issuer */
3493 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3494 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3495 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3496 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3497 if (ret)
3499 ok(size == sizeof(distPointWithUrlAndIssuer),
3500 "Wrong size %d\n", size);
3501 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3502 LocalFree(buf);
3506 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3508 BOOL ret;
3509 BYTE *buf = NULL;
3510 DWORD size = 0;
3511 PCRL_DIST_POINTS_INFO info;
3512 PCRL_DIST_POINT point;
3513 PCERT_ALT_NAME_ENTRY entry;
3515 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3516 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3517 &buf, &size);
3518 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3519 if (ret)
3521 info = (PCRL_DIST_POINTS_INFO)buf;
3522 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3523 "Wrong size %d\n", size);
3524 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3525 info->cDistPoint);
3526 point = info->rgDistPoint;
3527 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3528 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3529 point->DistPointName.dwDistPointNameChoice);
3530 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3531 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3532 LocalFree(buf);
3534 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3535 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3536 &buf, &size);
3537 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3538 if (ret)
3540 info = (PCRL_DIST_POINTS_INFO)buf;
3541 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3542 "Wrong size %d\n", size);
3543 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3544 info->cDistPoint);
3545 point = info->rgDistPoint;
3546 ok(point->DistPointName.dwDistPointNameChoice ==
3547 CRL_DIST_POINT_FULL_NAME,
3548 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3549 point->DistPointName.dwDistPointNameChoice);
3550 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3551 "Expected 1 name entry, got %d\n",
3552 U(point->DistPointName).FullName.cAltEntry);
3553 entry = U(point->DistPointName).FullName.rgAltEntry;
3554 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3555 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3556 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3557 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3558 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3559 LocalFree(buf);
3561 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3562 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3563 NULL, &buf, &size);
3564 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3565 if (ret)
3567 info = (PCRL_DIST_POINTS_INFO)buf;
3568 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3569 "Wrong size %d\n", size);
3570 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3571 info->cDistPoint);
3572 point = info->rgDistPoint;
3573 ok(point->DistPointName.dwDistPointNameChoice ==
3574 CRL_DIST_POINT_NO_NAME,
3575 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3576 point->DistPointName.dwDistPointNameChoice);
3577 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3578 "Expected reason length\n");
3579 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3580 "Unexpected reason\n");
3581 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3582 LocalFree(buf);
3584 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3585 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3586 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3587 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3588 if (ret)
3590 info = (PCRL_DIST_POINTS_INFO)buf;
3591 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3592 "Wrong size %d\n", size);
3593 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3594 info->cDistPoint);
3595 point = info->rgDistPoint;
3596 ok(point->DistPointName.dwDistPointNameChoice ==
3597 CRL_DIST_POINT_FULL_NAME,
3598 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3599 point->DistPointName.dwDistPointNameChoice);
3600 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3601 "Expected 1 name entry, got %d\n",
3602 U(point->DistPointName).FullName.cAltEntry);
3603 entry = U(point->DistPointName).FullName.rgAltEntry;
3604 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3605 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3606 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3607 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3608 ok(point->CRLIssuer.cAltEntry == 1,
3609 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3610 entry = point->CRLIssuer.rgAltEntry;
3611 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3612 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3613 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3614 LocalFree(buf);
3616 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3617 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3618 NULL, NULL, &size);
3619 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3620 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3621 if (buf)
3623 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3624 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3625 NULL, buf, &size);
3626 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3627 HeapFree(GetProcessHeap(), 0, buf);
3631 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3632 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3633 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3634 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3635 0x67 };
3637 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3639 BOOL ret;
3640 BYTE *buf = NULL;
3641 DWORD size = 0;
3642 CRL_ISSUING_DIST_POINT point = { { 0 } };
3643 CERT_ALT_NAME_ENTRY entry;
3645 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3646 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3647 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3649 skip("no X509_ISSUING_DIST_POINT encode support\n");
3650 return;
3652 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3653 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3654 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3655 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3656 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3657 if (ret)
3659 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3660 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3661 LocalFree(buf);
3663 /* nonsensical flags */
3664 point.fOnlyContainsUserCerts = TRUE;
3665 point.fOnlyContainsCACerts = TRUE;
3666 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3667 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3668 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3669 if (ret)
3671 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3672 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3673 LocalFree(buf);
3675 /* unimplemented name type */
3676 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3677 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3678 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3679 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3680 ok(!ret && GetLastError() == E_INVALIDARG,
3681 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3682 /* empty name */
3683 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3684 U(point.DistPointName).FullName.cAltEntry = 0;
3685 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3686 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3687 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3688 if (ret)
3690 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3691 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3692 LocalFree(buf);
3694 /* name with URL entry */
3695 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3696 U(entry).pwszURL = (LPWSTR)url;
3697 U(point.DistPointName).FullName.cAltEntry = 1;
3698 U(point.DistPointName).FullName.rgAltEntry = &entry;
3699 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3700 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3701 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3702 if (ret)
3704 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3705 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3706 LocalFree(buf);
3710 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3711 const CERT_ALT_NAME_ENTRY *got)
3713 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3714 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3715 got->dwAltNameChoice);
3716 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3718 switch (got->dwAltNameChoice)
3720 case CERT_ALT_NAME_RFC822_NAME:
3721 case CERT_ALT_NAME_DNS_NAME:
3722 case CERT_ALT_NAME_EDI_PARTY_NAME:
3723 case CERT_ALT_NAME_URL:
3724 case CERT_ALT_NAME_REGISTERED_ID:
3725 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3726 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3727 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3728 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3729 "Unexpected name\n");
3730 break;
3731 case CERT_ALT_NAME_X400_ADDRESS:
3732 case CERT_ALT_NAME_DIRECTORY_NAME:
3733 case CERT_ALT_NAME_IP_ADDRESS:
3734 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3735 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3736 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3737 U(*got).IPAddress.cbData), "Unexpected value\n");
3738 break;
3743 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3744 const CERT_ALT_NAME_INFO *got)
3746 DWORD i;
3748 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3749 expected->cAltEntry, got->cAltEntry);
3750 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3751 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3754 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3755 const CRL_DIST_POINT_NAME *got)
3757 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3758 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3759 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3760 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3763 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3764 const CRL_ISSUING_DIST_POINT *got)
3766 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3767 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3768 "Unexpected fOnlyContainsUserCerts\n");
3769 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3770 "Unexpected fOnlyContainsCACerts\n");
3771 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3772 "Unexpected reason flags\n");
3773 ok(got->fIndirectCRL == expected->fIndirectCRL,
3774 "Unexpected fIndirectCRL\n");
3777 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3779 BOOL ret;
3780 BYTE *buf = NULL;
3781 DWORD size = 0;
3782 CRL_ISSUING_DIST_POINT point = { { 0 } };
3784 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3785 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3786 &buf, &size);
3787 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3789 skip("no X509_ISSUING_DIST_POINT decode support\n");
3790 return;
3792 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3793 if (ret)
3795 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3796 LocalFree(buf);
3798 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3799 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3800 &buf, &size);
3801 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3802 if (ret)
3804 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3805 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3806 LocalFree(buf);
3808 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3809 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3810 &buf, &size);
3811 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3812 if (ret)
3814 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3815 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3816 U(point.DistPointName).FullName.cAltEntry = 0;
3817 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3818 LocalFree(buf);
3820 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3821 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3822 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3823 if (ret)
3825 CERT_ALT_NAME_ENTRY entry;
3827 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3828 U(entry).pwszURL = (LPWSTR)url;
3829 U(point.DistPointName).FullName.cAltEntry = 1;
3830 U(point.DistPointName).FullName.rgAltEntry = &entry;
3831 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3832 LocalFree(buf);
3836 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3837 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3838 0x30, 0x5a };
3839 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3840 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3841 0x30, 0x30, 0x30, 0x30, 0x5a };
3842 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3843 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3844 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3845 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3846 0x5a };
3847 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3848 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3849 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3850 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3851 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3852 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3853 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3854 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3855 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3856 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3857 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3858 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3859 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3860 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3861 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3862 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3863 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3864 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3865 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3866 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3867 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3868 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3869 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3870 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3871 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3872 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3873 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3874 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3875 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3876 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3877 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3878 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3879 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3881 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3883 BOOL ret;
3884 BYTE *buf = NULL;
3885 DWORD size = 0;
3886 CRL_INFO info = { 0 };
3887 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3889 /* Test with a V1 CRL */
3890 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3891 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3892 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3893 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3894 if (ret)
3896 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3897 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3898 LocalFree(buf);
3900 /* Test v2 CRL */
3901 info.dwVersion = CRL_V2;
3902 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3903 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3904 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3905 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3906 if (ret)
3908 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3909 v2CRL[1] + 2, size);
3910 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3911 LocalFree(buf);
3913 /* v1 CRL with a name */
3914 info.dwVersion = CRL_V1;
3915 info.Issuer.cbData = sizeof(encodedCommonName);
3916 info.Issuer.pbData = (BYTE *)encodedCommonName;
3917 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3918 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3919 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3920 if (ret)
3922 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3923 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3924 LocalFree(buf);
3926 if (0)
3928 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3929 info.cCRLEntry = 1;
3930 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3931 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3932 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3933 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3935 /* now set an empty entry */
3936 info.cCRLEntry = 1;
3937 info.rgCRLEntry = &entry;
3938 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3939 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3940 if (ret)
3942 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3943 "Wrong size %d\n", size);
3944 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3945 "Got unexpected value\n");
3946 LocalFree(buf);
3948 /* an entry with a serial number */
3949 entry.SerialNumber.cbData = sizeof(serialNum);
3950 entry.SerialNumber.pbData = (BYTE *)serialNum;
3951 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3952 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3953 if (ret)
3955 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3956 "Wrong size %d\n", size);
3957 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3958 "Got unexpected value\n");
3959 LocalFree(buf);
3961 /* an entry with an extension */
3962 entry.cExtension = 1;
3963 entry.rgExtension = &criticalExt;
3964 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3965 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3966 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3967 if (ret)
3969 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3970 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3971 LocalFree(buf);
3973 /* a CRL with an extension */
3974 entry.cExtension = 0;
3975 info.cExtension = 1;
3976 info.rgExtension = &criticalExt;
3977 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3978 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3979 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3980 if (ret)
3982 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3983 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3984 LocalFree(buf);
3986 /* a v2 CRL with an extension, this time non-critical */
3987 info.dwVersion = CRL_V2;
3988 info.rgExtension = &nonCriticalExt;
3989 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3990 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3991 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3992 if (ret)
3994 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3995 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3996 LocalFree(buf);
4000 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
4001 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4002 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
4003 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
4004 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
4005 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
4006 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4007 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4008 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4009 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4010 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4011 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4012 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4013 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4014 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4015 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4016 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4017 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4018 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4019 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4020 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4021 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4022 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4023 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4024 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4025 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4026 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4027 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4028 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4029 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4030 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4031 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4032 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4033 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4034 0xcd };
4035 static const BYTE verisignCRLWithLotsOfEntries[] = {
4036 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4037 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4038 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4039 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4040 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4041 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4042 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4043 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4044 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4045 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4046 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4047 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4048 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4049 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4050 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4051 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4052 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4053 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4054 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4055 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4056 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4057 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4058 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4059 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4060 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4061 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4062 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4063 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4064 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4065 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4066 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4067 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4068 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4069 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4070 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4071 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4072 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4073 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4074 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4075 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4076 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4077 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4078 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4079 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4080 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4081 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4082 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4083 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4084 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4085 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4086 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4087 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4088 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4089 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4090 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4091 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4092 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4093 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4094 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4095 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4096 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4097 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4098 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4099 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4100 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4101 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4102 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4103 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4104 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4105 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4106 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4107 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4108 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4109 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4110 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4111 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4112 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4113 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4114 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4115 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4116 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4117 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4118 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4119 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4120 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4121 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4122 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4123 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4124 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4125 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4126 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4127 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4128 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4129 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4130 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4131 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4132 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4133 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4134 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4135 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4136 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4137 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4138 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4139 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4140 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4141 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4142 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4143 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4144 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4145 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4146 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4147 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4148 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4149 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4150 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4151 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4152 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4153 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4154 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4155 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4156 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4157 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4158 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4159 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4160 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4161 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4162 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4163 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4164 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4165 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4166 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4167 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4168 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4169 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4170 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4171 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4172 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4173 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4174 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4175 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4176 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4177 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4178 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4179 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4180 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4181 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4182 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4183 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4184 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4185 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4186 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4187 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4188 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4189 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4190 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4191 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4192 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4193 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4194 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4195 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4196 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4197 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4198 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4199 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4200 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4201 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4202 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4203 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4204 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4205 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4206 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4207 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4208 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4209 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4210 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4211 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4212 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4213 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4214 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4215 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4216 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4217 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4218 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4219 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4220 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4221 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4222 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4223 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4224 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4225 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4226 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4227 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4228 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4229 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4230 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4231 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4232 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4233 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4234 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4235 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4236 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4237 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4238 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4239 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4240 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4241 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4242 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4243 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4244 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4245 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4246 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4247 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4248 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4249 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4250 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4251 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4252 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4253 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4254 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4255 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4256 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4257 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4258 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4259 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4260 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4261 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4262 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4263 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4264 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4265 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4266 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4267 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4268 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4269 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4270 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4271 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4272 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4273 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4274 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4275 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4276 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4277 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4278 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4279 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4280 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4281 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4282 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4283 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4284 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4285 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4286 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4287 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4288 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4289 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4290 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4291 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4292 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4293 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4294 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4295 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4296 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4297 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4298 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4299 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4300 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4301 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4302 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4303 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4304 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4305 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4306 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4307 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4308 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4309 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4310 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4311 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4312 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4313 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4314 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4315 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4316 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4317 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4318 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4319 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4320 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4321 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4322 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4323 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4324 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4325 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4326 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4327 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4328 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4329 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4330 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4331 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4332 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4333 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4334 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4335 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4336 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4337 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4338 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4339 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4340 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4341 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4342 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4343 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4344 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4345 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4346 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4347 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4348 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4349 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4350 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4351 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4352 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4353 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4354 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4355 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4356 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4357 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4358 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4359 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4360 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4361 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4362 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4363 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4364 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4365 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4366 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4367 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4368 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4369 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4370 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4371 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4372 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4373 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4374 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4375 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4376 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4377 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4378 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4379 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4380 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4381 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4382 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4383 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4384 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4385 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4386 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4387 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4388 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4389 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4390 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4391 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4392 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4393 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4394 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4395 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4396 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4397 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4398 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4399 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4400 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4401 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4402 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4403 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4404 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4405 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4406 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4407 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4408 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4409 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4410 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4411 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4412 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4413 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4414 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4415 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4416 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4417 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4418 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4419 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4420 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4421 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4422 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4423 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4424 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4425 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4426 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4427 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4428 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4429 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4430 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4431 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4432 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4433 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4434 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4435 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4436 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4437 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4438 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4439 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4440 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4441 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4442 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4443 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4444 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4445 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4446 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4447 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4448 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4449 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4450 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4451 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4452 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4453 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4454 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4455 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4456 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4457 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4458 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4459 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4460 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4461 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4462 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4463 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4464 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4465 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4466 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4467 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4468 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4469 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4470 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4471 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4472 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4473 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4474 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4475 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4476 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4477 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4478 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4479 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4480 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4481 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4482 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4483 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4484 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4485 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4486 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4487 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4488 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4489 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4490 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4491 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4492 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4493 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4494 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4495 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4496 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4497 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4498 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4499 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4500 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4501 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4502 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4503 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4504 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4505 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4506 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4507 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4508 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4509 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4510 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4511 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4512 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4513 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4514 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4515 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4516 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4517 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4518 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4519 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4520 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4521 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4522 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4523 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4524 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4525 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4526 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4527 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4528 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4529 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4530 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4531 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4532 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4533 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4534 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4535 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4536 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4537 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4538 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4539 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4540 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4541 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4542 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4543 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4545 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4547 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4548 BOOL ret;
4549 BYTE *buf = NULL;
4550 DWORD size = 0, i;
4552 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4554 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4555 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4556 &buf, &size);
4557 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4558 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4559 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4560 GetLastError());
4562 /* at a minimum, a CRL must contain an issuer: */
4563 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4564 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4565 &buf, &size);
4566 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4567 if (ret)
4569 CRL_INFO *info = (CRL_INFO *)buf;
4571 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4572 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4573 info->cCRLEntry);
4574 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4575 "Wrong issuer size %d\n", info->Issuer.cbData);
4576 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4577 "Unexpected issuer\n");
4578 LocalFree(buf);
4580 /* check decoding with an empty CRL entry */
4581 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4582 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4583 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4584 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4585 GetLastError() == OSS_DATA_ERROR /* Win9x */ ||
4586 GetLastError() == CRYPT_E_BAD_ENCODE /* Win8 */),
4587 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4588 GetLastError());
4589 /* with a real CRL entry */
4590 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4591 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4592 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4593 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4594 if (ret)
4596 CRL_INFO *info = (CRL_INFO *)buf;
4597 CRL_ENTRY *entry;
4599 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4600 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4601 info->cCRLEntry);
4602 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4603 entry = info->rgCRLEntry;
4604 ok(entry->SerialNumber.cbData == 1,
4605 "Expected serial number size 1, got %d\n",
4606 entry->SerialNumber.cbData);
4607 ok(*entry->SerialNumber.pbData == *serialNum,
4608 "Expected serial number %d, got %d\n", *serialNum,
4609 *entry->SerialNumber.pbData);
4610 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4611 "Wrong issuer size %d\n", info->Issuer.cbData);
4612 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4613 "Unexpected issuer\n");
4614 LocalFree(buf);
4616 /* a real CRL from verisign that has extensions */
4617 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4618 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4619 NULL, &buf, &size);
4620 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4621 if (ret)
4623 CRL_INFO *info = (CRL_INFO *)buf;
4625 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4626 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4627 info->cCRLEntry);
4628 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4629 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4630 info->cExtension);
4631 LocalFree(buf);
4633 /* another real CRL from verisign that has lots of entries */
4634 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4635 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4636 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4637 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4638 if (ret)
4640 CRL_INFO *info = (CRL_INFO *)buf;
4642 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4643 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4644 info->cCRLEntry);
4645 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4646 info->cExtension);
4647 LocalFree(buf);
4649 /* and finally, with an extension */
4650 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4651 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4652 NULL, &buf, &size);
4653 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4654 if (ret)
4656 CRL_INFO *info = (CRL_INFO *)buf;
4657 CRL_ENTRY *entry;
4659 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4660 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4661 info->cCRLEntry);
4662 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4663 entry = info->rgCRLEntry;
4664 ok(entry->SerialNumber.cbData == 1,
4665 "Expected serial number size 1, got %d\n",
4666 entry->SerialNumber.cbData);
4667 ok(*entry->SerialNumber.pbData == *serialNum,
4668 "Expected serial number %d, got %d\n", *serialNum,
4669 *entry->SerialNumber.pbData);
4670 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4671 "Wrong issuer size %d\n", info->Issuer.cbData);
4672 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4673 "Unexpected issuer\n");
4674 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4675 info->cExtension);
4676 LocalFree(buf);
4678 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4679 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4680 NULL, &buf, &size);
4681 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4682 if (ret)
4684 CRL_INFO *info = (CRL_INFO *)buf;
4686 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4687 info->cExtension);
4688 LocalFree(buf);
4692 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4693 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4694 static const BYTE encodedUsage[] = {
4695 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4696 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4697 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4699 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4701 BOOL ret;
4702 BYTE *buf = NULL;
4703 DWORD size = 0;
4704 CERT_ENHKEY_USAGE usage;
4706 /* Test with empty usage */
4707 usage.cUsageIdentifier = 0;
4708 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4709 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4710 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4711 if (ret)
4713 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4714 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4715 LocalFree(buf);
4717 /* Test with a few usages */
4718 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4719 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4720 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4721 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4722 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4723 if (ret)
4725 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4726 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4727 LocalFree(buf);
4731 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4733 BOOL ret;
4734 LPBYTE buf = NULL;
4735 DWORD size = 0;
4737 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4738 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4739 &buf, &size);
4740 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4741 if (ret)
4743 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4745 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4746 "Wrong size %d\n", size);
4747 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4748 usage->cUsageIdentifier);
4749 LocalFree(buf);
4751 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4752 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4753 &buf, &size);
4754 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4755 if (ret)
4757 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4758 DWORD i;
4760 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4761 "Wrong size %d\n", size);
4762 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4763 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4764 for (i = 0; i < usage->cUsageIdentifier; i++)
4765 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4766 "Expected OID %s, got %s\n", keyUsages[i],
4767 usage->rgpszUsageIdentifier[i]);
4768 LocalFree(buf);
4770 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4771 encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4772 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4773 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4774 if (buf)
4776 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4777 encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4778 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4779 HeapFree(GetProcessHeap(), 0, buf);
4783 static BYTE keyId[] = { 1,2,3,4 };
4784 static const BYTE authorityKeyIdWithId[] = {
4785 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4786 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4787 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4788 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4789 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4791 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4793 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4794 BOOL ret;
4795 BYTE *buf = NULL;
4796 DWORD size = 0;
4798 /* Test with empty id */
4799 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4800 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4801 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4802 if (ret)
4804 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4805 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4806 LocalFree(buf);
4808 /* With just a key id */
4809 info.KeyId.cbData = sizeof(keyId);
4810 info.KeyId.pbData = keyId;
4811 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4812 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4813 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4814 if (ret)
4816 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4817 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4818 LocalFree(buf);
4820 /* With just an issuer */
4821 info.KeyId.cbData = 0;
4822 info.CertIssuer.cbData = sizeof(encodedCommonName);
4823 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4824 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4825 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4826 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4827 if (ret)
4829 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4830 size);
4831 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4832 LocalFree(buf);
4834 /* With just a serial number */
4835 info.CertIssuer.cbData = 0;
4836 info.CertSerialNumber.cbData = sizeof(serialNum);
4837 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4838 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4839 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4840 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4841 if (ret)
4843 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4844 size);
4845 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4846 LocalFree(buf);
4850 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4852 BOOL ret;
4853 LPBYTE buf = NULL;
4854 DWORD size = 0;
4856 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4857 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4858 &buf, &size);
4859 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4860 if (ret)
4862 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4864 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4865 size);
4866 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4867 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4868 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4869 LocalFree(buf);
4871 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4872 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4873 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4874 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4875 if (ret)
4877 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4879 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4880 size);
4881 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4882 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4883 "Unexpected key id\n");
4884 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4885 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4886 LocalFree(buf);
4888 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4889 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4890 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4891 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4892 if (ret)
4894 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4896 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4897 size);
4898 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4899 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4900 "Unexpected issuer len\n");
4901 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4902 sizeof(encodedCommonName)), "Unexpected issuer\n");
4903 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4904 LocalFree(buf);
4906 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4907 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4908 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4909 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4910 if (ret)
4912 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4914 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4915 size);
4916 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4917 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4918 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4919 "Unexpected serial number len\n");
4920 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4921 "Unexpected serial number\n");
4922 LocalFree(buf);
4926 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4927 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4928 0x6f,0x72,0x67 };
4930 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4932 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4933 CERT_ALT_NAME_ENTRY entry = { 0 };
4934 BOOL ret;
4935 BYTE *buf = NULL;
4936 DWORD size = 0;
4938 /* Test with empty id */
4939 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4940 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4941 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4942 if (ret)
4944 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4945 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4946 LocalFree(buf);
4948 /* With just a key id */
4949 info.KeyId.cbData = sizeof(keyId);
4950 info.KeyId.pbData = keyId;
4951 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4952 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4953 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4954 if (ret)
4956 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4957 size);
4958 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4959 LocalFree(buf);
4961 /* With a bogus issuer name */
4962 info.KeyId.cbData = 0;
4963 info.AuthorityCertIssuer.cAltEntry = 1;
4964 info.AuthorityCertIssuer.rgAltEntry = &entry;
4965 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4966 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4967 ok(!ret && GetLastError() == E_INVALIDARG,
4968 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4969 /* With an issuer name */
4970 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4971 U(entry).pwszURL = (LPWSTR)url;
4972 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4973 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4974 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4975 if (ret)
4977 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4978 size);
4979 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4980 "Unexpected value\n");
4981 LocalFree(buf);
4983 /* With just a serial number */
4984 info.AuthorityCertIssuer.cAltEntry = 0;
4985 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4986 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4987 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4988 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4989 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4990 if (ret)
4992 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4993 size);
4994 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4995 LocalFree(buf);
4999 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
5001 BOOL ret;
5002 LPBYTE buf = NULL;
5003 DWORD size = 0;
5005 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5006 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5007 &buf, &size);
5008 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5009 if (ret)
5011 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5013 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5014 size);
5015 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5016 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5017 "Expected no issuer name entries\n");
5018 ok(info->AuthorityCertSerialNumber.cbData == 0,
5019 "Expected no serial number\n");
5020 LocalFree(buf);
5022 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5023 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5024 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5025 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5026 if (ret)
5028 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5030 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5031 size);
5032 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5033 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5034 "Unexpected key id\n");
5035 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5036 "Expected no issuer name entries\n");
5037 ok(info->AuthorityCertSerialNumber.cbData == 0,
5038 "Expected no serial number\n");
5039 LocalFree(buf);
5041 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5042 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5043 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5044 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5045 if (ret)
5047 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5049 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5050 size);
5051 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5052 ok(info->AuthorityCertIssuer.cAltEntry == 1,
5053 "Expected 1 issuer entry, got %d\n",
5054 info->AuthorityCertIssuer.cAltEntry);
5055 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5056 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5057 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5058 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5059 url), "Unexpected URL\n");
5060 ok(info->AuthorityCertSerialNumber.cbData == 0,
5061 "Expected no serial number\n");
5062 LocalFree(buf);
5064 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5065 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5066 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5067 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5068 if (ret)
5070 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5072 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5073 size);
5074 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5075 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5076 "Expected no issuer name entries\n");
5077 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5078 "Unexpected serial number len\n");
5079 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5080 sizeof(serialNum)), "Unexpected serial number\n");
5081 LocalFree(buf);
5085 static const BYTE authorityInfoAccessWithUrl[] = {
5086 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5087 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5088 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5089 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5090 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5091 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5093 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5095 static char oid1[] = "1.2.3";
5096 static char oid2[] = "1.5.6";
5097 BOOL ret;
5098 BYTE *buf = NULL;
5099 DWORD size = 0;
5100 CERT_ACCESS_DESCRIPTION accessDescription[2];
5101 CERT_AUTHORITY_INFO_ACCESS aia;
5103 memset(accessDescription, 0, sizeof(accessDescription));
5104 aia.cAccDescr = 0;
5105 aia.rgAccDescr = NULL;
5106 /* Having no access descriptions is allowed */
5107 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5108 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5109 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5110 if (ret)
5112 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5113 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5114 LocalFree(buf);
5115 buf = NULL;
5117 /* It can't have an empty access method */
5118 aia.cAccDescr = 1;
5119 aia.rgAccDescr = accessDescription;
5120 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5121 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5122 ok(!ret && (GetLastError() == E_INVALIDARG ||
5123 GetLastError() == OSS_LIMITED /* Win9x */),
5124 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5125 /* It can't have an empty location */
5126 accessDescription[0].pszAccessMethod = oid1;
5127 SetLastError(0xdeadbeef);
5128 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5129 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5130 ok(!ret && GetLastError() == E_INVALIDARG,
5131 "expected E_INVALIDARG, got %08x\n", GetLastError());
5132 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5133 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5134 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5135 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5136 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5137 if (ret)
5139 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5140 size);
5141 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5142 "unexpected value\n");
5143 LocalFree(buf);
5144 buf = NULL;
5146 accessDescription[1].pszAccessMethod = oid2;
5147 accessDescription[1].AccessLocation.dwAltNameChoice =
5148 CERT_ALT_NAME_IP_ADDRESS;
5149 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5150 sizeof(encodedIPAddr);
5151 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5152 (LPBYTE)encodedIPAddr;
5153 aia.cAccDescr = 2;
5154 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5155 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5156 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5157 if (ret)
5159 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5160 "unexpected size %d\n", size);
5161 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5162 "unexpected value\n");
5163 LocalFree(buf);
5164 buf = NULL;
5168 static void compareAuthorityInfoAccess(LPCSTR header,
5169 const CERT_AUTHORITY_INFO_ACCESS *expected,
5170 const CERT_AUTHORITY_INFO_ACCESS *got)
5172 DWORD i;
5174 ok(expected->cAccDescr == got->cAccDescr,
5175 "%s: expected %d access descriptions, got %d\n", header,
5176 expected->cAccDescr, got->cAccDescr);
5177 for (i = 0; i < expected->cAccDescr; i++)
5179 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5180 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5181 header, i, expected->rgAccDescr[i].pszAccessMethod,
5182 got->rgAccDescr[i].pszAccessMethod);
5183 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5184 &got->rgAccDescr[i].AccessLocation);
5188 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5190 static char oid1[] = "1.2.3";
5191 static char oid2[] = "1.5.6";
5192 BOOL ret;
5193 LPBYTE buf = NULL;
5194 DWORD size = 0;
5196 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5197 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5198 &buf, &size);
5199 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5200 if (ret)
5202 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5204 compareAuthorityInfoAccess("empty AIA", &aia,
5205 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5206 LocalFree(buf);
5207 buf = NULL;
5209 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5210 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5211 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5212 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5213 if (ret)
5215 CERT_ACCESS_DESCRIPTION accessDescription;
5216 CERT_AUTHORITY_INFO_ACCESS aia;
5218 accessDescription.pszAccessMethod = oid1;
5219 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5220 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5221 aia.cAccDescr = 1;
5222 aia.rgAccDescr = &accessDescription;
5223 compareAuthorityInfoAccess("AIA with URL", &aia,
5224 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5225 LocalFree(buf);
5226 buf = NULL;
5228 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5229 authorityInfoAccessWithUrlAndIPAddr,
5230 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5231 NULL, &buf, &size);
5232 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5233 if (ret)
5235 CERT_ACCESS_DESCRIPTION accessDescription[2];
5236 CERT_AUTHORITY_INFO_ACCESS aia;
5238 accessDescription[0].pszAccessMethod = oid1;
5239 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5240 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5241 accessDescription[1].pszAccessMethod = oid2;
5242 accessDescription[1].AccessLocation.dwAltNameChoice =
5243 CERT_ALT_NAME_IP_ADDRESS;
5244 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5245 sizeof(encodedIPAddr);
5246 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5247 (LPBYTE)encodedIPAddr;
5248 aia.cAccDescr = 2;
5249 aia.rgAccDescr = accessDescription;
5250 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5251 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5252 LocalFree(buf);
5253 buf = NULL;
5255 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5256 authorityInfoAccessWithUrlAndIPAddr,
5257 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5258 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5259 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5260 if (buf)
5262 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5263 authorityInfoAccessWithUrlAndIPAddr,
5264 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5265 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5266 HeapFree(GetProcessHeap(), 0, buf);
5270 static const BYTE emptyCTL[] = {
5271 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5272 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5273 static const BYTE emptyCTLWithVersion1[] = {
5274 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5275 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5276 static const BYTE ctlWithUsageIdentifier[] = {
5277 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5278 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5279 static const BYTE ctlWithListIdentifier[] = {
5280 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5281 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5282 static const BYTE ctlWithSequenceNumber[] = {
5283 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5284 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5285 static const BYTE ctlWithThisUpdate[] = {
5286 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5287 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5288 static const BYTE ctlWithThisAndNextUpdate[] = {
5289 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5290 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5291 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5292 static const BYTE ctlWithAlgId[] = {
5293 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5294 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5295 static const BYTE ctlWithBogusEntry[] = {
5296 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5297 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5298 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5299 static const BYTE ctlWithOneEntry[] = {
5300 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5301 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5302 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5303 static const BYTE ctlWithTwoEntries[] = {
5304 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5305 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5306 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5307 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5308 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5310 static void test_encodeCTL(DWORD dwEncoding)
5312 static char oid1[] = "1.2.3";
5313 static char oid2[] = "1.5.6";
5314 char *pOid1 = oid1;
5315 BOOL ret;
5316 BYTE *buf = NULL;
5317 DWORD size = 0;
5318 CTL_INFO info;
5319 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5320 CTL_ENTRY ctlEntry[2];
5321 CRYPT_ATTRIBUTE attr1, attr2;
5322 CRYPT_ATTR_BLOB value1, value2;
5324 memset(&info, 0, sizeof(info));
5325 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5326 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5327 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5328 if (ret)
5330 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5331 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5332 LocalFree(buf);
5333 buf = NULL;
5335 info.dwVersion = 1;
5336 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5337 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5338 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5339 if (ret)
5341 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5342 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5343 LocalFree(buf);
5344 buf = NULL;
5346 info.dwVersion = 0;
5347 info.SubjectUsage.cUsageIdentifier = 1;
5348 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5349 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5350 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5351 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5352 if (ret)
5354 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5355 size);
5356 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5357 LocalFree(buf);
5358 buf = NULL;
5360 info.SubjectUsage.cUsageIdentifier = 0;
5361 info.ListIdentifier.cbData = sizeof(serialNum);
5362 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5363 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5364 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5365 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5366 if (ret)
5368 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5369 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5370 LocalFree(buf);
5371 buf = NULL;
5373 info.ListIdentifier.cbData = 0;
5374 info.SequenceNumber.cbData = sizeof(serialNum);
5375 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5376 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5377 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5378 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5379 if (ret)
5381 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5382 size);
5383 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5384 LocalFree(buf);
5385 buf = NULL;
5387 info.SequenceNumber.cbData = 0;
5388 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5389 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5390 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5391 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5392 if (ret)
5394 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5395 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5396 LocalFree(buf);
5397 buf = NULL;
5399 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5400 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5401 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5402 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5403 if (ret)
5405 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5406 size);
5407 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5408 LocalFree(buf);
5409 buf = NULL;
5411 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5412 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5413 info.SubjectAlgorithm.pszObjId = oid2;
5414 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5415 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5416 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5417 if (ret)
5419 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5420 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5421 LocalFree(buf);
5422 buf = NULL;
5424 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5425 * (see tests below) but it'll encode fine.
5427 info.SubjectAlgorithm.pszObjId = NULL;
5428 value1.cbData = sizeof(serialNum);
5429 value1.pbData = (LPBYTE)serialNum;
5430 attr1.pszObjId = oid1;
5431 attr1.cValue = 1;
5432 attr1.rgValue = &value1;
5433 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5434 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5435 ctlEntry[0].cAttribute = 1;
5436 ctlEntry[0].rgAttribute = &attr1;
5437 info.cCTLEntry = 1;
5438 info.rgCTLEntry = ctlEntry;
5439 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5440 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5441 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5442 if (ret)
5444 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5445 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5446 LocalFree(buf);
5447 buf = NULL;
5449 value1.cbData = sizeof(emptySequence);
5450 value1.pbData = (LPBYTE)emptySequence;
5451 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5452 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5453 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5454 if (ret)
5456 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5457 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5458 LocalFree(buf);
5459 buf = NULL;
5461 value2.cbData = sizeof(encodedIPAddr);
5462 value2.pbData = (LPBYTE)encodedIPAddr;
5463 attr2.pszObjId = oid2;
5464 attr2.cValue = 1;
5465 attr2.rgValue = &value2;
5466 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5467 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5468 ctlEntry[1].cAttribute = 1;
5469 ctlEntry[1].rgAttribute = &attr2;
5470 info.cCTLEntry = 2;
5471 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5473 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5474 if (ret)
5476 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5477 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5478 LocalFree(buf);
5479 buf = NULL;
5483 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5484 const CTL_INFO *got)
5486 DWORD i, j, k;
5488 ok(expected->dwVersion == got->dwVersion,
5489 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5490 got->dwVersion);
5491 ok(expected->SubjectUsage.cUsageIdentifier ==
5492 got->SubjectUsage.cUsageIdentifier,
5493 "%s: expected %d usage identifiers, got %d\n", header,
5494 expected->SubjectUsage.cUsageIdentifier,
5495 got->SubjectUsage.cUsageIdentifier);
5496 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5497 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5498 got->SubjectUsage.rgpszUsageIdentifier[i]),
5499 "%s[%d]: expected %s, got %s\n", header, i,
5500 expected->SubjectUsage.rgpszUsageIdentifier[i],
5501 got->SubjectUsage.rgpszUsageIdentifier[i]);
5502 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5503 "%s: expected list identifier of %d bytes, got %d\n", header,
5504 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5505 if (expected->ListIdentifier.cbData)
5506 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5507 expected->ListIdentifier.cbData),
5508 "%s: unexpected list identifier value\n", header);
5509 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5510 "%s: expected sequence number of %d bytes, got %d\n", header,
5511 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5512 if (expected->SequenceNumber.cbData)
5513 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5514 expected->SequenceNumber.cbData),
5515 "%s: unexpected sequence number value\n", header);
5516 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5517 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5518 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5519 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5520 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5521 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5522 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5523 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5524 if (expected->SubjectAlgorithm.pszObjId &&
5525 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5526 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5527 expected->SubjectAlgorithm.pszObjId);
5528 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5529 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5530 got->SubjectAlgorithm.pszObjId),
5531 "%s: expected subject algorithm %s, got %s\n", header,
5532 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5533 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5534 got->SubjectAlgorithm.Parameters.cbData,
5535 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5536 expected->SubjectAlgorithm.Parameters.cbData,
5537 got->SubjectAlgorithm.Parameters.cbData);
5538 if (expected->SubjectAlgorithm.Parameters.cbData)
5539 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5540 got->SubjectAlgorithm.Parameters.pbData,
5541 expected->SubjectAlgorithm.Parameters.cbData),
5542 "%s: unexpected subject algorithm parameter value\n", header);
5543 ok(expected->cCTLEntry == got->cCTLEntry,
5544 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5545 got->cCTLEntry);
5546 for (i = 0; i < expected->cCTLEntry; i++)
5548 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5549 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5550 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5551 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5552 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5553 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5554 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5555 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5556 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5557 "%s[%d]: unexpected subject identifier value\n",
5558 header, i);
5559 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5561 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5562 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5563 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5564 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5565 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5566 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5568 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5569 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5570 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5571 header, i, j, k,
5572 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5573 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5574 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5575 ok(!memcmp(
5576 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5577 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5578 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5579 "%s[%d][%d][%d]: unexpected value\n",
5580 header, i, j, k);
5584 ok(expected->cExtension == got->cExtension,
5585 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5586 got->cExtension);
5587 for (i = 0; i < expected->cExtension; i++)
5589 ok(!strcmp(expected->rgExtension[i].pszObjId,
5590 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5591 header, i, expected->rgExtension[i].pszObjId,
5592 got->rgExtension[i].pszObjId);
5593 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5594 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5595 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5596 ok(expected->rgExtension[i].Value.cbData ==
5597 got->rgExtension[i].Value.cbData,
5598 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5599 header, i, expected->rgExtension[i].Value.cbData,
5600 got->rgExtension[i].Value.cbData);
5601 if (expected->rgExtension[i].Value.cbData)
5602 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5603 got->rgExtension[i].Value.pbData,
5604 expected->rgExtension[i].Value.cbData),
5605 "%s[%d]: unexpected extension value\n", header, i);
5609 static const BYTE signedCTL[] = {
5610 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5611 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5612 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5613 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5614 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5615 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5616 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5617 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5618 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5619 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5620 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5621 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5622 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5623 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5624 static const BYTE signedCTLWithCTLInnerContent[] = {
5625 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5626 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5627 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5628 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5629 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5630 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5631 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5632 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5633 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5634 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5635 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5636 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5637 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5638 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5639 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5640 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5641 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5642 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5643 0x57,0x6c,0x0b,0x47,0xb8 };
5645 static void test_decodeCTL(DWORD dwEncoding)
5647 static char oid1[] = "1.2.3";
5648 static char oid2[] = "1.5.6";
5649 static BYTE nullData[] = { 5,0 };
5650 char *pOid1 = oid1;
5651 BOOL ret;
5652 BYTE *buf = NULL;
5653 DWORD size = 0;
5654 CTL_INFO info;
5655 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5656 CTL_ENTRY ctlEntry[2];
5657 CRYPT_ATTRIBUTE attr1, attr2;
5658 CRYPT_ATTR_BLOB value1, value2;
5660 memset(&info, 0, sizeof(info));
5661 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5662 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5663 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5664 if (ret)
5666 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5667 LocalFree(buf);
5668 buf = NULL;
5670 info.dwVersion = 1;
5671 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5672 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5673 &size);
5674 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5675 if (ret)
5677 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5678 LocalFree(buf);
5679 buf = NULL;
5681 info.dwVersion = 0;
5682 info.SubjectUsage.cUsageIdentifier = 1;
5683 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5684 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5685 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5686 &buf, &size);
5687 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5688 if (ret)
5690 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5691 LocalFree(buf);
5692 buf = NULL;
5694 info.SubjectUsage.cUsageIdentifier = 0;
5695 info.ListIdentifier.cbData = sizeof(serialNum);
5696 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5697 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5698 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5699 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5700 if (ret)
5702 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5703 LocalFree(buf);
5704 buf = NULL;
5706 info.ListIdentifier.cbData = 0;
5707 info.SequenceNumber.cbData = sizeof(serialNum);
5708 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5709 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5710 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5711 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5712 if (ret)
5714 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5715 LocalFree(buf);
5716 buf = NULL;
5718 info.SequenceNumber.cbData = 0;
5719 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5720 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5721 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5722 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5723 if (ret)
5725 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5726 LocalFree(buf);
5727 buf = NULL;
5729 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5730 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5731 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5732 &buf, &size);
5733 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5734 if (ret)
5736 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5737 LocalFree(buf);
5738 buf = NULL;
5740 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5741 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5742 info.SubjectAlgorithm.pszObjId = oid2;
5743 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5744 info.SubjectAlgorithm.Parameters.pbData = nullData;
5745 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5746 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5747 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5748 if (ret)
5750 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5751 LocalFree(buf);
5752 buf = NULL;
5754 SetLastError(0xdeadbeef);
5755 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5756 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5757 ok(!ret &&
5758 (GetLastError() == CRYPT_E_ASN1_EOD ||
5759 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5760 GetLastError() == OSS_MORE_INPUT), /* Win9x */
5761 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5762 GetLastError());
5763 info.SubjectAlgorithm.Parameters.cbData = 0;
5764 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5765 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5766 info.SubjectAlgorithm.pszObjId = oid2;
5767 info.SubjectAlgorithm.pszObjId = NULL;
5768 value1.cbData = sizeof(emptySequence);
5769 value1.pbData = (LPBYTE)emptySequence;
5770 attr1.pszObjId = oid1;
5771 attr1.cValue = 1;
5772 attr1.rgValue = &value1;
5773 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5774 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5775 ctlEntry[0].cAttribute = 1;
5776 ctlEntry[0].rgAttribute = &attr1;
5777 info.cCTLEntry = 1;
5778 info.rgCTLEntry = ctlEntry;
5779 SetLastError(0xdeadbeef);
5780 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5781 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5782 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5783 if (ret)
5785 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5786 LocalFree(buf);
5787 buf = NULL;
5789 value2.cbData = sizeof(encodedIPAddr);
5790 value2.pbData = (LPBYTE)encodedIPAddr;
5791 attr2.pszObjId = oid2;
5792 attr2.cValue = 1;
5793 attr2.rgValue = &value2;
5794 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5795 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5796 ctlEntry[1].cAttribute = 1;
5797 ctlEntry[1].rgAttribute = &attr2;
5798 info.cCTLEntry = 2;
5799 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5800 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5801 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5802 if (ret)
5804 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5805 LocalFree(buf);
5806 buf = NULL;
5808 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5809 SetLastError(0xdeadbeef);
5810 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5811 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5812 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5813 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5814 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5815 GetLastError());
5816 SetLastError(0xdeadbeef);
5817 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5818 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5819 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5820 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5821 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5822 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5823 GetLastError());
5826 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5827 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5828 0x03,0,0,0,0,0,0 };
5829 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5830 0xa0,0x01,0x01 };
5831 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5832 0x03,0x02,0x01,0x01 };
5833 static BYTE bogusDER[] = { 1 };
5835 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5837 BOOL ret;
5838 BYTE *buf = NULL;
5839 DWORD size = 0;
5840 CRYPT_CONTENT_INFO info = { 0 };
5841 char oid1[] = "1.2.3";
5843 if (0)
5845 /* Crashes on win9x */
5846 SetLastError(0xdeadbeef);
5847 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5848 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5849 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5850 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5852 SetLastError(0xdeadbeef);
5853 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5854 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5855 ok(!ret && (GetLastError() == E_INVALIDARG ||
5856 GetLastError() == OSS_LIMITED /* Win9x */),
5857 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5858 info.pszObjId = oid1;
5859 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5860 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5861 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5862 if (ret)
5864 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5865 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5866 LocalFree(buf);
5868 info.Content.pbData = bogusDER;
5869 info.Content.cbData = sizeof(bogusDER);
5870 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5871 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5872 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5873 if (ret)
5875 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5876 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5877 LocalFree(buf);
5879 info.Content.pbData = (BYTE *)ints[0].encoded;
5880 info.Content.cbData = ints[0].encoded[1] + 2;
5881 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5882 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5883 if (ret)
5885 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5886 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5887 LocalFree(buf);
5891 static const BYTE indefiniteSignedPKCSContent[] = {
5892 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5893 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5894 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5895 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5896 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5897 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5898 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5899 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5900 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5901 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5902 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5903 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5904 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5905 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5906 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5907 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5908 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5909 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5910 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5911 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5912 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5913 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5914 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5915 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5916 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5917 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5918 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5919 0x00,0x00,0x00,0x00,0x00,0x00 };
5921 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5923 BOOL ret;
5924 LPBYTE buf = NULL;
5925 DWORD size = 0;
5926 CRYPT_CONTENT_INFO *info;
5928 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5929 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5930 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5931 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5932 if (ret)
5934 info = (CRYPT_CONTENT_INFO *)buf;
5936 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5937 info->pszObjId);
5938 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5939 info->Content.cbData);
5940 LocalFree(buf);
5942 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5943 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5944 0, NULL, NULL, &size);
5945 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5946 SetLastError(0xdeadbeef);
5947 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5948 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5949 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5950 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5951 * I doubt an app depends on that.
5953 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5954 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5955 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5956 GetLastError());
5957 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5958 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5959 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5960 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5961 if (ret)
5963 info = (CRYPT_CONTENT_INFO *)buf;
5965 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5966 info->pszObjId);
5967 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5968 "Unexpected size %d\n", info->Content.cbData);
5969 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5970 info->Content.cbData), "Unexpected value\n");
5971 LocalFree(buf);
5973 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5974 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5975 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5976 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5977 if (ret)
5979 info = (CRYPT_CONTENT_INFO *)buf;
5981 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5982 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5983 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5984 info->Content.cbData);
5985 LocalFree(buf);
5989 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5990 0x00 };
5991 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5992 0x01 };
5993 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5994 0x02,0x01,0x01 };
5996 static void test_encodePKCSAttribute(DWORD dwEncoding)
5998 CRYPT_ATTRIBUTE attr = { 0 };
5999 BOOL ret;
6000 LPBYTE buf = NULL;
6001 DWORD size = 0;
6002 CRYPT_ATTR_BLOB blob;
6003 char oid[] = "1.2.3";
6005 if (0)
6007 /* Crashes on win9x */
6008 SetLastError(0xdeadbeef);
6009 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6010 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6011 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6012 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6014 SetLastError(0xdeadbeef);
6015 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6016 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6017 ok(!ret && (GetLastError() == E_INVALIDARG ||
6018 GetLastError() == OSS_LIMITED /* Win9x */),
6019 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6020 attr.pszObjId = oid;
6021 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6022 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6023 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6024 if (ret)
6026 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6027 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6028 LocalFree(buf);
6030 blob.cbData = sizeof(bogusDER);
6031 blob.pbData = bogusDER;
6032 attr.cValue = 1;
6033 attr.rgValue = &blob;
6034 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6035 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6036 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6037 if (ret)
6039 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6040 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6041 LocalFree(buf);
6043 blob.pbData = (BYTE *)ints[0].encoded;
6044 blob.cbData = ints[0].encoded[1] + 2;
6045 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6046 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6047 if (ret)
6049 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6050 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6051 LocalFree(buf);
6055 static void test_decodePKCSAttribute(DWORD dwEncoding)
6057 BOOL ret;
6058 LPBYTE buf = NULL;
6059 DWORD size = 0;
6060 CRYPT_ATTRIBUTE *attr;
6062 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6063 emptyPKCSAttr, sizeof(emptyPKCSAttr),
6064 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6065 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6066 if (ret)
6068 attr = (CRYPT_ATTRIBUTE *)buf;
6070 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6071 attr->pszObjId);
6072 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6073 LocalFree(buf);
6075 SetLastError(0xdeadbeef);
6076 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6077 bogusPKCSAttr, sizeof(bogusPKCSAttr),
6078 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6079 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6080 * I doubt an app depends on that.
6082 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6083 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6084 GetLastError() == OSS_MORE_INPUT /* Win9x */),
6085 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6086 GetLastError());
6087 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6088 intPKCSAttr, sizeof(intPKCSAttr),
6089 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6090 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6091 if (ret)
6093 attr = (CRYPT_ATTRIBUTE *)buf;
6095 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6096 attr->pszObjId);
6097 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6098 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6099 "Unexpected size %d\n", attr->rgValue[0].cbData);
6100 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6101 attr->rgValue[0].cbData), "Unexpected value\n");
6102 LocalFree(buf);
6106 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6107 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6108 0x2a,0x03,0x31,0x00 };
6109 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6110 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6112 static void test_encodePKCSAttributes(DWORD dwEncoding)
6114 CRYPT_ATTRIBUTES attributes = { 0 };
6115 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6116 CRYPT_ATTR_BLOB blob;
6117 BOOL ret;
6118 LPBYTE buf = NULL;
6119 DWORD size = 0;
6120 char oid1[] = "1.2.3", oid2[] = "1.5.6";
6122 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6123 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6124 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6125 if (ret)
6127 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6128 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6129 LocalFree(buf);
6131 attributes.cAttr = 1;
6132 attributes.rgAttr = attr;
6133 SetLastError(0xdeadbeef);
6134 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6135 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6136 ok(!ret && (GetLastError() == E_INVALIDARG ||
6137 GetLastError() == OSS_LIMITED /* Win9x */),
6138 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6139 attr[0].pszObjId = oid1;
6140 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6142 if (ret)
6144 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6145 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6146 LocalFree(buf);
6148 attr[1].pszObjId = oid2;
6149 attr[1].cValue = 1;
6150 attr[1].rgValue = &blob;
6151 blob.pbData = (BYTE *)ints[0].encoded;
6152 blob.cbData = ints[0].encoded[1] + 2;
6153 attributes.cAttr = 2;
6154 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6155 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6156 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6157 if (ret)
6159 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6160 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6161 LocalFree(buf);
6165 static void test_decodePKCSAttributes(DWORD dwEncoding)
6167 BOOL ret;
6168 LPBYTE buf = NULL;
6169 DWORD size = 0;
6170 CRYPT_ATTRIBUTES *attributes;
6172 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6173 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6174 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6175 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6176 if (ret)
6178 attributes = (CRYPT_ATTRIBUTES *)buf;
6179 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6180 attributes->cAttr);
6181 LocalFree(buf);
6183 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6184 singlePKCSAttributes, sizeof(singlePKCSAttributes),
6185 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6186 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6187 if (ret)
6189 attributes = (CRYPT_ATTRIBUTES *)buf;
6190 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6191 attributes->cAttr);
6192 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6193 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6194 ok(attributes->rgAttr[0].cValue == 0,
6195 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6196 LocalFree(buf);
6198 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6199 doublePKCSAttributes, sizeof(doublePKCSAttributes),
6200 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6201 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6202 if (ret)
6204 attributes = (CRYPT_ATTRIBUTES *)buf;
6205 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6206 attributes->cAttr);
6207 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6208 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6209 ok(attributes->rgAttr[0].cValue == 0,
6210 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6211 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6212 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6213 ok(attributes->rgAttr[1].cValue == 1,
6214 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6215 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6216 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6217 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6218 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6219 LocalFree(buf);
6221 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6222 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6223 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6224 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6225 if (buf)
6227 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6228 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6229 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6230 HeapFree(GetProcessHeap(), 0, buf);
6234 static const BYTE singleCapability[] = {
6235 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6236 static const BYTE twoCapabilities[] = {
6237 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6238 static const BYTE singleCapabilitywithNULL[] = {
6239 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6241 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6243 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6244 BOOL ret;
6245 LPBYTE buf = NULL;
6246 DWORD size = 0;
6247 CRYPT_SMIME_CAPABILITY capability[2];
6248 CRYPT_SMIME_CAPABILITIES capabilities;
6250 /* An empty capabilities is allowed */
6251 capabilities.cCapability = 0;
6252 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6253 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6254 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6255 if (ret)
6257 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6258 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6259 LocalFree(buf);
6261 /* A non-empty capabilities with an empty capability (lacking an OID) is
6262 * not allowed
6264 capability[0].pszObjId = NULL;
6265 capability[0].Parameters.cbData = 0;
6266 capabilities.cCapability = 1;
6267 capabilities.rgCapability = capability;
6268 SetLastError(0xdeadbeef);
6269 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6270 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6271 ok(!ret && (GetLastError() == E_INVALIDARG ||
6272 GetLastError() == OSS_LIMITED /* Win9x */),
6273 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6274 capability[0].pszObjId = oid1;
6275 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6276 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6277 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6278 if (ret)
6280 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6281 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6282 LocalFree(buf);
6284 capability[1].pszObjId = oid2;
6285 capability[1].Parameters.cbData = 0;
6286 capabilities.cCapability = 2;
6287 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6288 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6289 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6290 if (ret)
6292 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6293 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6294 LocalFree(buf);
6298 static void compareSMimeCapabilities(LPCSTR header,
6299 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6301 DWORD i;
6303 ok(got->cCapability == expected->cCapability,
6304 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6305 got->cCapability);
6306 for (i = 0; i < expected->cCapability; i++)
6308 ok(!strcmp(expected->rgCapability[i].pszObjId,
6309 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6310 header, i, expected->rgCapability[i].pszObjId,
6311 got->rgCapability[i].pszObjId);
6312 ok(expected->rgCapability[i].Parameters.cbData ==
6313 got->rgCapability[i].Parameters.cbData,
6314 "%s[%d]: expected %d bytes, got %d\n", header, i,
6315 expected->rgCapability[i].Parameters.cbData,
6316 got->rgCapability[i].Parameters.cbData);
6317 if (expected->rgCapability[i].Parameters.cbData)
6318 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6319 got->rgCapability[i].Parameters.pbData,
6320 expected->rgCapability[i].Parameters.cbData),
6321 "%s[%d]: unexpected value\n", header, i);
6325 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6327 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6328 BOOL ret;
6329 DWORD size = 0;
6330 CRYPT_SMIME_CAPABILITY capability[2];
6331 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6333 SetLastError(0xdeadbeef);
6334 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6335 emptySequence, sizeof(emptySequence),
6336 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6337 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6338 if (ret)
6340 capabilities.cCapability = 0;
6341 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6342 LocalFree(ptr);
6344 SetLastError(0xdeadbeef);
6345 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6346 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6347 &ptr, &size);
6348 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6349 if (ret)
6351 capability[0].pszObjId = oid1;
6352 capability[0].Parameters.cbData = 0;
6353 capabilities.cCapability = 1;
6354 capabilities.rgCapability = capability;
6355 compareSMimeCapabilities("single capability", &capabilities, ptr);
6356 LocalFree(ptr);
6358 SetLastError(0xdeadbeef);
6359 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6360 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6361 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6362 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6363 if (ret)
6365 BYTE NULLparam[] = {0x05, 0x00};
6366 capability[0].pszObjId = oid1;
6367 capability[0].Parameters.cbData = 2;
6368 capability[0].Parameters.pbData = NULLparam;
6369 capabilities.cCapability = 1;
6370 capabilities.rgCapability = capability;
6371 compareSMimeCapabilities("single capability with NULL", &capabilities,
6372 ptr);
6373 LocalFree(ptr);
6375 SetLastError(0xdeadbeef);
6376 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6377 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6378 &ptr, &size);
6379 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6380 if (ret)
6382 capability[0].Parameters.cbData = 0;
6383 capability[1].pszObjId = oid2;
6384 capability[1].Parameters.cbData = 0;
6385 capabilities.cCapability = 2;
6386 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6387 LocalFree(ptr);
6389 SetLastError(0xdeadbeef);
6390 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6391 twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6392 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6393 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6394 if (ptr)
6396 SetLastError(0xdeadbeef);
6397 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6398 twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6399 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6400 HeapFree(GetProcessHeap(), 0, ptr);
6404 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6405 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6406 0x67 };
6407 static const BYTE minimalPKCSSigner[] = {
6408 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6409 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6410 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6411 static const BYTE PKCSSignerWithSerial[] = {
6412 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6413 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6414 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6415 0x00 };
6416 static const BYTE PKCSSignerWithHashAlgo[] = {
6417 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6418 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6419 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6420 0x00,0x04,0x00 };
6421 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6422 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6423 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6424 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6425 0x06,0x05,0x00,0x04,0x00 };
6426 static const BYTE PKCSSignerWithHash[] = {
6427 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6428 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6429 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6430 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6431 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6432 static const BYTE PKCSSignerWithAuthAttr[] = {
6433 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6434 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6435 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6436 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6437 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6438 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6439 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6441 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6443 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6444 BOOL ret;
6445 LPBYTE buf = NULL;
6446 DWORD size = 0;
6447 CMSG_SIGNER_INFO info = { 0 };
6448 char oid_common_name[] = szOID_COMMON_NAME;
6449 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6450 (LPBYTE)encodedCommonName };
6451 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6453 SetLastError(0xdeadbeef);
6454 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6455 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6456 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6458 skip("no PKCS7_SIGNER_INFO encode support\n");
6459 return;
6461 ok(!ret && (GetLastError() == E_INVALIDARG ||
6462 GetLastError() == OSS_LIMITED /* Win9x */),
6463 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6464 /* To be encoded, a signer must have an issuer at least, and the encoding
6465 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6466 * see decoding tests.)
6468 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6469 info.Issuer.pbData = encodedCommonNameNoNull;
6470 SetLastError(0xdeadbeef);
6471 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6473 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6474 ok(!ret && GetLastError() == E_INVALIDARG,
6475 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6476 else
6478 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6479 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6480 if (ret)
6482 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6483 if (size == sizeof(minimalPKCSSigner))
6484 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6485 else
6486 ok(0, "Unexpected value\n");
6487 LocalFree(buf);
6490 info.SerialNumber.cbData = sizeof(serialNum);
6491 info.SerialNumber.pbData = (BYTE *)serialNum;
6492 SetLastError(0xdeadbeef);
6493 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6494 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6495 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6496 ok(!ret && GetLastError() == E_INVALIDARG,
6497 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6498 else
6500 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6501 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6502 if (ret)
6504 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6505 size);
6506 if (size == sizeof(PKCSSignerWithSerial))
6507 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6508 "Unexpected value\n");
6509 else
6510 ok(0, "Unexpected value\n");
6511 LocalFree(buf);
6514 info.HashAlgorithm.pszObjId = oid1;
6515 SetLastError(0xdeadbeef);
6516 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6517 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6518 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6519 ok(!ret && GetLastError() == E_INVALIDARG,
6520 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6521 else
6523 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6524 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6525 if (ret)
6527 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6528 size);
6529 if (size == sizeof(PKCSSignerWithHashAlgo))
6530 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6531 "Unexpected value\n");
6532 else
6533 ok(0, "Unexpected value\n");
6534 LocalFree(buf);
6537 info.HashEncryptionAlgorithm.pszObjId = oid2;
6538 SetLastError(0xdeadbeef);
6539 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6540 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6541 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6542 ok(!ret && GetLastError() == E_INVALIDARG,
6543 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6544 else
6546 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6547 if (ret)
6549 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6550 "Unexpected size %d\n", size);
6551 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6552 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6553 "Unexpected value\n");
6554 else
6555 ok(0, "Unexpected value\n");
6556 LocalFree(buf);
6559 info.EncryptedHash.cbData = sizeof(hash);
6560 info.EncryptedHash.pbData = (BYTE *)hash;
6561 SetLastError(0xdeadbeef);
6562 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6563 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6564 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6565 ok(!ret && GetLastError() == E_INVALIDARG,
6566 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6567 else
6569 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6570 if (ret)
6572 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6573 size);
6574 if (size == sizeof(PKCSSignerWithHash))
6575 ok(!memcmp(buf, PKCSSignerWithHash, size),
6576 "Unexpected value\n");
6577 else
6578 ok(0, "Unexpected value\n");
6579 LocalFree(buf);
6582 info.AuthAttrs.cAttr = 1;
6583 info.AuthAttrs.rgAttr = &attr;
6584 SetLastError(0xdeadbeef);
6585 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6586 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6587 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6588 ok(!ret && GetLastError() == E_INVALIDARG,
6589 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6590 else
6592 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6593 if (ret)
6595 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6596 size);
6597 if (size == sizeof(PKCSSignerWithAuthAttr))
6598 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6599 "Unexpected value\n");
6600 else
6601 ok(0, "Unexpected value\n");
6602 LocalFree(buf);
6607 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6609 BOOL ret;
6610 LPBYTE buf = NULL;
6611 DWORD size = 0;
6612 CMSG_SIGNER_INFO *info;
6614 /* A PKCS signer can't be decoded without a serial number. */
6615 SetLastError(0xdeadbeef);
6616 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6617 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6618 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6619 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6620 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6621 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6622 GetLastError());
6623 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6624 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6625 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6626 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6627 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6628 if (ret)
6630 info = (CMSG_SIGNER_INFO *)buf;
6631 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6632 info->dwVersion);
6633 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6634 "Unexpected size %d\n", info->Issuer.cbData);
6635 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6636 info->Issuer.cbData), "Unexpected value\n");
6637 ok(info->SerialNumber.cbData == sizeof(serialNum),
6638 "Unexpected size %d\n", info->SerialNumber.cbData);
6639 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6640 "Unexpected value\n");
6641 LocalFree(buf);
6643 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6644 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6645 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6646 if (ret)
6648 info = (CMSG_SIGNER_INFO *)buf;
6649 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6650 info->dwVersion);
6651 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6652 "Unexpected size %d\n", info->Issuer.cbData);
6653 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6654 info->Issuer.cbData), "Unexpected value\n");
6655 ok(info->SerialNumber.cbData == sizeof(serialNum),
6656 "Unexpected size %d\n", info->SerialNumber.cbData);
6657 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6658 "Unexpected value\n");
6659 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6660 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6661 LocalFree(buf);
6663 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6664 PKCSSignerWithHashAndEncryptionAlgo,
6665 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6666 NULL, &buf, &size);
6667 if (ret)
6669 info = (CMSG_SIGNER_INFO *)buf;
6670 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6671 info->dwVersion);
6672 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6673 "Unexpected size %d\n", info->Issuer.cbData);
6674 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6675 info->Issuer.cbData), "Unexpected value\n");
6676 ok(info->SerialNumber.cbData == sizeof(serialNum),
6677 "Unexpected size %d\n", info->SerialNumber.cbData);
6678 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6679 "Unexpected value\n");
6680 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6681 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6682 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6683 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6684 LocalFree(buf);
6686 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6687 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6688 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6689 if (ret)
6691 info = (CMSG_SIGNER_INFO *)buf;
6692 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6693 info->dwVersion);
6694 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6695 "Unexpected size %d\n", info->Issuer.cbData);
6696 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6697 info->Issuer.cbData), "Unexpected value\n");
6698 ok(info->SerialNumber.cbData == sizeof(serialNum),
6699 "Unexpected size %d\n", info->SerialNumber.cbData);
6700 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6701 "Unexpected value\n");
6702 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6703 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6704 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6705 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6706 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6707 info->EncryptedHash.cbData);
6708 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6709 "Unexpected value\n");
6710 LocalFree(buf);
6712 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6713 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6714 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6715 if (ret)
6717 info = (CMSG_SIGNER_INFO *)buf;
6718 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6719 info->AuthAttrs.cAttr);
6720 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6721 "Expected %s, got %s\n", szOID_COMMON_NAME,
6722 info->AuthAttrs.rgAttr[0].pszObjId);
6723 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6724 info->AuthAttrs.rgAttr[0].cValue);
6725 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6726 sizeof(encodedCommonName), "Unexpected size %d\n",
6727 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6728 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6729 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6730 LocalFree(buf);
6734 static const BYTE CMSSignerWithKeyId[] = {
6735 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6736 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6738 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6740 BOOL ret;
6741 LPBYTE buf = NULL;
6742 DWORD size = 0;
6743 CMSG_CMS_SIGNER_INFO info = { 0 };
6744 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6746 SetLastError(0xdeadbeef);
6747 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6748 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6749 ok(!ret, "Expected failure, got %d\n", ret);
6750 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6752 skip("no CMS_SIGNER_INFO encode support\n");
6753 return;
6755 ok(GetLastError() == E_INVALIDARG,
6756 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6757 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6758 SetLastError(0xdeadbeef);
6759 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6760 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6761 ok(!ret, "Expected failure, got %d\n", ret);
6762 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6764 skip("no CMS_SIGNER_INFO encode support\n");
6765 return;
6767 ok(GetLastError() == E_INVALIDARG,
6768 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6769 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6770 * be a key id or an issuer serial number with at least the issuer set, and
6771 * the encoding must include PKCS_7_ASN_ENCODING.
6772 * (That isn't enough to be decoded, see decoding tests.)
6774 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6775 sizeof(encodedCommonNameNoNull);
6776 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6777 SetLastError(0xdeadbeef);
6778 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6780 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6781 ok(!ret && GetLastError() == E_INVALIDARG,
6782 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6783 else
6785 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6786 if (ret)
6788 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6789 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6790 LocalFree(buf);
6793 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6794 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6795 SetLastError(0xdeadbeef);
6796 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6797 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6798 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6799 ok(!ret && GetLastError() == E_INVALIDARG,
6800 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6801 else
6803 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6804 if (ret)
6806 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6807 size);
6808 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6809 LocalFree(buf);
6812 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6813 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6814 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6815 SetLastError(0xdeadbeef);
6816 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6817 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6818 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6819 ok(!ret && GetLastError() == E_INVALIDARG,
6820 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6821 else
6823 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6824 if (ret)
6826 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6827 size);
6828 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6829 LocalFree(buf);
6832 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6833 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6834 * (see RFC 3852, section 5.3.)
6836 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6837 U(info.SignerId).HashId.cbData = sizeof(hash);
6838 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6839 SetLastError(0xdeadbeef);
6840 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6841 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6842 ok(!ret && GetLastError() == E_INVALIDARG,
6843 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6844 /* Now with a hash algo */
6845 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6846 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6847 sizeof(encodedCommonNameNoNull);
6848 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6849 info.HashAlgorithm.pszObjId = oid1;
6850 SetLastError(0xdeadbeef);
6851 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6852 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6853 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6854 ok(!ret && GetLastError() == E_INVALIDARG,
6855 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6856 else
6858 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6859 if (ret)
6861 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6862 size);
6863 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6864 "Unexpected value\n");
6865 LocalFree(buf);
6868 info.HashEncryptionAlgorithm.pszObjId = oid2;
6869 SetLastError(0xdeadbeef);
6870 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6871 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6872 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6873 ok(!ret && GetLastError() == E_INVALIDARG,
6874 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6875 else
6877 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6878 if (ret)
6880 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6881 "Unexpected size %d\n", size);
6882 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6883 "Unexpected value\n");
6884 LocalFree(buf);
6887 info.EncryptedHash.cbData = sizeof(hash);
6888 info.EncryptedHash.pbData = (BYTE *)hash;
6889 SetLastError(0xdeadbeef);
6890 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6891 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6892 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6893 ok(!ret && GetLastError() == E_INVALIDARG,
6894 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6895 else
6897 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6898 if (ret)
6900 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6901 size);
6902 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6903 LocalFree(buf);
6908 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6910 BOOL ret;
6911 LPBYTE buf = NULL;
6912 DWORD size = 0;
6913 CMSG_CMS_SIGNER_INFO *info;
6914 static const char oid1[] = "1.2.3", oid2[] = "1.5.6";
6916 /* A CMS signer can't be decoded without a serial number. */
6917 SetLastError(0xdeadbeef);
6918 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6919 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6920 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6921 ok(!ret, "expected failure\n");
6922 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6924 skip("no CMS_SIGNER_INFO decode support\n");
6925 return;
6927 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6928 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6929 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6930 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6931 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6932 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6933 if (ret)
6935 info = (CMSG_CMS_SIGNER_INFO *)buf;
6936 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6937 info->dwVersion);
6938 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6939 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6940 info->SignerId.dwIdChoice);
6941 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6942 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6943 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6944 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6945 encodedCommonNameNoNull,
6946 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6947 "Unexpected value\n");
6948 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6949 sizeof(serialNum), "Unexpected size %d\n",
6950 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6951 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6952 serialNum, sizeof(serialNum)), "Unexpected value\n");
6953 LocalFree(buf);
6955 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6956 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6957 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6958 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6959 if (ret)
6961 info = (CMSG_CMS_SIGNER_INFO *)buf;
6962 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6963 info->dwVersion);
6964 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6965 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6966 info->SignerId.dwIdChoice);
6967 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6968 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6969 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6970 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6971 encodedCommonNameNoNull,
6972 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6973 "Unexpected value\n");
6974 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6975 sizeof(serialNum), "Unexpected size %d\n",
6976 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6977 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6978 serialNum, sizeof(serialNum)), "Unexpected value\n");
6979 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6980 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6981 LocalFree(buf);
6983 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6984 PKCSSignerWithHashAndEncryptionAlgo,
6985 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6986 NULL, &buf, &size);
6987 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6988 if (ret)
6990 info = (CMSG_CMS_SIGNER_INFO *)buf;
6991 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6992 info->dwVersion);
6993 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6994 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6995 info->SignerId.dwIdChoice);
6996 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6997 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6998 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6999 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7000 encodedCommonNameNoNull,
7001 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7002 "Unexpected value\n");
7003 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7004 sizeof(serialNum), "Unexpected size %d\n",
7005 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7006 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7007 serialNum, sizeof(serialNum)), "Unexpected value\n");
7008 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7009 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7010 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7011 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7012 LocalFree(buf);
7014 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7015 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7016 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7017 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7018 if (ret)
7020 info = (CMSG_CMS_SIGNER_INFO *)buf;
7021 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7022 info->dwVersion);
7023 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7024 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7025 info->SignerId.dwIdChoice);
7026 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7027 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7028 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7029 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7030 encodedCommonNameNoNull,
7031 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7032 "Unexpected value\n");
7033 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7034 sizeof(serialNum), "Unexpected size %d\n",
7035 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7036 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7037 serialNum, sizeof(serialNum)), "Unexpected value\n");
7038 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7039 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7040 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7041 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7042 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7043 info->EncryptedHash.cbData);
7044 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7045 "Unexpected value\n");
7046 LocalFree(buf);
7048 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7049 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7050 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7051 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7052 if (ret)
7054 info = (CMSG_CMS_SIGNER_INFO *)buf;
7055 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7056 info->dwVersion);
7057 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7058 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7059 info->SignerId.dwIdChoice);
7060 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7061 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7062 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7063 "Unexpected value\n");
7064 LocalFree(buf);
7068 static BYTE emptyDNSPermittedConstraints[] = {
7069 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7070 static BYTE emptyDNSExcludedConstraints[] = {
7071 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7072 static BYTE DNSExcludedConstraints[] = {
7073 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7074 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7075 static BYTE permittedAndExcludedConstraints[] = {
7076 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7077 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7078 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7079 static BYTE permittedAndExcludedWithMinConstraints[] = {
7080 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7081 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7082 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7083 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7084 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7085 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7086 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7088 static void test_encodeNameConstraints(DWORD dwEncoding)
7090 BOOL ret;
7091 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7092 CERT_GENERAL_SUBTREE permitted = { { 0 } };
7093 CERT_GENERAL_SUBTREE excluded = { { 0 } };
7094 LPBYTE buf;
7095 DWORD size;
7097 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7098 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7099 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7101 skip("no X509_NAME_CONSTRAINTS encode support\n");
7102 return;
7104 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7105 if (ret)
7107 ok(size == sizeof(emptySequence), "Unexpected size\n");
7108 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7109 LocalFree(buf);
7111 constraints.cPermittedSubtree = 1;
7112 constraints.rgPermittedSubtree = &permitted;
7113 SetLastError(0xdeadbeef);
7114 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7115 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7116 ok(!ret && GetLastError() == E_INVALIDARG,
7117 "Expected E_INVALIDARG, got %08x\n", GetLastError());
7118 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7119 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7120 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7121 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7122 if (ret)
7124 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7125 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7126 "Unexpected value\n");
7127 LocalFree(buf);
7129 constraints.cPermittedSubtree = 0;
7130 constraints.cExcludedSubtree = 1;
7131 constraints.rgExcludedSubtree = &excluded;
7132 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7133 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7134 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7135 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7136 if (ret)
7138 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7139 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7140 "Unexpected value\n");
7141 LocalFree(buf);
7143 U(excluded.Base).pwszURL = (LPWSTR)url;
7144 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7145 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7146 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7147 if (ret)
7149 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7150 ok(!memcmp(buf, DNSExcludedConstraints, size),
7151 "Unexpected value\n");
7152 LocalFree(buf);
7154 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7155 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7156 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7157 constraints.cPermittedSubtree = 1;
7158 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7159 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7160 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7161 if (ret)
7163 ok(size == sizeof(permittedAndExcludedConstraints),
7164 "Unexpected size\n");
7165 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7166 "Unexpected value\n");
7167 LocalFree(buf);
7169 permitted.dwMinimum = 5;
7170 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7171 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7172 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7173 if (ret)
7175 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7176 "Unexpected size\n");
7177 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7178 "Unexpected value\n");
7179 LocalFree(buf);
7181 permitted.fMaximum = TRUE;
7182 permitted.dwMaximum = 3;
7183 SetLastError(0xdeadbeef);
7184 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7185 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7186 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7187 if (ret)
7189 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7190 "Unexpected size\n");
7191 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7192 "Unexpected value\n");
7193 LocalFree(buf);
7197 struct EncodedNameConstraints
7199 CRYPT_DATA_BLOB encoded;
7200 CERT_NAME_CONSTRAINTS_INFO constraints;
7203 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7204 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7205 static CERT_GENERAL_SUBTREE DNSSubtree = {
7206 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7207 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7208 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7209 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7210 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7211 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7212 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7214 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7215 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7216 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7217 { 1, &emptyDNSSubtree, 0, NULL } },
7218 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7219 { 0, NULL, 1, &emptyDNSSubtree } },
7220 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7221 { 0, NULL, 1, &DNSSubtree } },
7222 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7223 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7224 { { sizeof(permittedAndExcludedWithMinConstraints),
7225 permittedAndExcludedWithMinConstraints },
7226 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7227 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7228 permittedAndExcludedWithMinMaxConstraints },
7229 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7232 static void test_decodeNameConstraints(DWORD dwEncoding)
7234 BOOL ret;
7235 DWORD i;
7236 CERT_NAME_CONSTRAINTS_INFO *constraints;
7238 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7239 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7240 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7241 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7242 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7243 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7244 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7245 for (i = 0;
7246 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7247 i++)
7249 DWORD size;
7251 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7252 encodedNameConstraints[i].encoded.pbData,
7253 encodedNameConstraints[i].encoded.cbData,
7254 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7255 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7257 skip("no X509_NAME_CONSTRAINTS decode support\n");
7258 return;
7260 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7261 if (ret)
7263 DWORD j;
7265 if (constraints->cPermittedSubtree !=
7266 encodedNameConstraints[i].constraints.cPermittedSubtree)
7267 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7268 encodedNameConstraints[i].constraints.cPermittedSubtree,
7269 constraints->cPermittedSubtree);
7270 if (constraints->cPermittedSubtree ==
7271 encodedNameConstraints[i].constraints.cPermittedSubtree)
7273 for (j = 0; j < constraints->cPermittedSubtree; j++)
7275 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7276 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7279 if (constraints->cExcludedSubtree !=
7280 encodedNameConstraints[i].constraints.cExcludedSubtree)
7281 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7282 encodedNameConstraints[i].constraints.cExcludedSubtree,
7283 constraints->cExcludedSubtree);
7284 if (constraints->cExcludedSubtree ==
7285 encodedNameConstraints[i].constraints.cExcludedSubtree)
7287 for (j = 0; j < constraints->cExcludedSubtree; j++)
7289 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7290 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7293 LocalFree(constraints);
7298 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7299 'n','o','t','i','c','e',0 };
7300 static const BYTE noticeWithDisplayText[] = {
7301 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7302 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7303 0x00,0x69,0x00,0x63,0x00,0x65
7305 static char org[] = "Wine";
7306 static int noticeNumbers[] = { 2,3 };
7307 static BYTE noticeWithReference[] = {
7308 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7309 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7310 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7311 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7314 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7316 BOOL ret;
7317 LPBYTE buf;
7318 DWORD size;
7319 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7320 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7322 memset(&notice, 0, sizeof(notice));
7323 ret = pCryptEncodeObjectEx(dwEncoding,
7324 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7325 NULL, &buf, &size);
7326 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7328 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7329 return;
7331 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7332 if (ret)
7334 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7335 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7336 LocalFree(buf);
7338 notice.pszDisplayText = noticeText;
7339 ret = pCryptEncodeObjectEx(dwEncoding,
7340 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7341 NULL, &buf, &size);
7342 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7343 if (ret)
7345 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7346 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7347 LocalFree(buf);
7349 reference.pszOrganization = org;
7350 reference.cNoticeNumbers = 2;
7351 reference.rgNoticeNumbers = noticeNumbers;
7352 notice.pNoticeReference = &reference;
7353 ret = pCryptEncodeObjectEx(dwEncoding,
7354 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7355 NULL, &buf, &size);
7356 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7357 if (ret)
7359 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7360 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7361 LocalFree(buf);
7365 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7367 BOOL ret;
7368 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7369 DWORD size;
7371 ret = pCryptDecodeObjectEx(dwEncoding,
7372 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7373 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7374 &notice, &size);
7375 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7377 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7378 return;
7380 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7381 if (ret)
7383 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7384 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7385 LocalFree(notice);
7387 ret = pCryptDecodeObjectEx(dwEncoding,
7388 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7389 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7390 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7391 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7392 if (ret)
7394 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7395 "unexpected display text\n");
7396 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7397 LocalFree(notice);
7399 ret = pCryptDecodeObjectEx(dwEncoding,
7400 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7401 noticeWithReference, sizeof(noticeWithReference),
7402 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7403 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7404 if (ret)
7406 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7407 "unexpected display text\n");
7408 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7409 if (notice->pNoticeReference)
7411 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7412 "unexpected organization %s\n",
7413 notice->pNoticeReference->pszOrganization);
7414 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7415 "expected 2 notice numbers, got %d\n",
7416 notice->pNoticeReference->cNoticeNumbers);
7417 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7418 "unexpected notice number %d\n",
7419 notice->pNoticeReference->rgNoticeNumbers[0]);
7420 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7421 "unexpected notice number %d\n",
7422 notice->pNoticeReference->rgNoticeNumbers[1]);
7424 LocalFree(notice);
7428 static char oid_any_policy[] = "2.5.29.32.0";
7429 static const BYTE policiesWithAnyPolicy[] = {
7430 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7432 static char oid1[] = "1.2.3";
7433 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7434 static const BYTE twoPolicies[] = {
7435 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7436 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7437 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7438 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7439 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7440 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7443 static void test_encodeCertPolicies(DWORD dwEncoding)
7445 BOOL ret;
7446 CERT_POLICIES_INFO info;
7447 CERT_POLICY_INFO policy[2];
7448 CERT_POLICY_QUALIFIER_INFO qualifier;
7449 LPBYTE buf;
7450 DWORD size;
7452 memset(&info, 0, sizeof(info));
7453 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7454 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7455 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7456 if (ret)
7458 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7459 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7460 LocalFree(buf);
7462 memset(policy, 0, sizeof(policy));
7463 info.cPolicyInfo = 1;
7464 info.rgPolicyInfo = policy;
7465 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7466 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7467 ok(!ret && (GetLastError() == E_INVALIDARG ||
7468 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7469 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7470 policy[0].pszPolicyIdentifier = oid_any_policy;
7471 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7473 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7474 if (ret)
7476 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7477 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7478 LocalFree(buf);
7480 policy[1].pszPolicyIdentifier = oid1;
7481 memset(&qualifier, 0, sizeof(qualifier));
7482 qualifier.pszPolicyQualifierId = oid_user_notice;
7483 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7484 qualifier.Qualifier.pbData = noticeWithReference;
7485 policy[1].cPolicyQualifier = 1;
7486 policy[1].rgPolicyQualifier = &qualifier;
7487 info.cPolicyInfo = 2;
7488 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7489 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7490 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7491 if (ret)
7493 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7494 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7495 LocalFree(buf);
7499 static void test_decodeCertPolicies(DWORD dwEncoding)
7501 BOOL ret;
7502 CERT_POLICIES_INFO *info;
7503 DWORD size;
7505 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7506 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7507 &info, &size);
7508 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7509 if (ret)
7511 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7512 info->cPolicyInfo);
7513 LocalFree(info);
7515 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7516 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7517 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7518 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7519 if (ret)
7521 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7522 info->cPolicyInfo);
7523 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7524 "unexpected policy id %s\n",
7525 info->rgPolicyInfo[0].pszPolicyIdentifier);
7526 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7527 "unexpected policy qualifier count %d\n",
7528 info->rgPolicyInfo[0].cPolicyQualifier);
7529 LocalFree(info);
7531 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7532 twoPolicies, sizeof(twoPolicies),
7533 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7534 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7535 if (ret)
7537 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7538 info->cPolicyInfo);
7539 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7540 "unexpected policy id %s\n",
7541 info->rgPolicyInfo[0].pszPolicyIdentifier);
7542 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7543 "unexpected policy qualifier count %d\n",
7544 info->rgPolicyInfo[0].cPolicyQualifier);
7545 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7546 "unexpected policy id %s\n",
7547 info->rgPolicyInfo[1].pszPolicyIdentifier);
7548 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7549 "unexpected policy qualifier count %d\n",
7550 info->rgPolicyInfo[1].cPolicyQualifier);
7551 ok(!strcmp(
7552 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7553 oid_user_notice), "unexpected policy qualifier id %s\n",
7554 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7555 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7556 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7557 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7558 ok(!memcmp(
7559 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7560 noticeWithReference, sizeof(noticeWithReference)),
7561 "unexpected qualifier value\n");
7562 LocalFree(info);
7564 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7565 twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7566 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7567 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7568 if (info)
7570 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7571 twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7572 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7573 HeapFree(GetProcessHeap(), 0, info);
7577 static const BYTE policyMappingWithOneMapping[] = {
7578 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7579 static const BYTE policyMappingWithTwoMappings[] = {
7580 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7581 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7582 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7583 szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7585 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7587 static char oid2[] = "2.3.4";
7588 static char oid3[] = "1.3.4";
7589 static char oid4[] = "2.5.6";
7590 BOOL ret;
7591 CERT_POLICY_MAPPINGS_INFO info = { 0 };
7592 CERT_POLICY_MAPPING mapping[2];
7593 LPBYTE buf;
7594 DWORD size, i;
7596 /* Each of the mapping OIDs is equivalent, so check with all of them */
7597 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7599 memset(&info, 0, sizeof(info));
7600 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7601 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7602 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7603 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7604 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7606 win_skip("no policy mappings support\n");
7607 return;
7609 if (ret)
7611 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7612 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7613 "unexpected value\n");
7614 LocalFree(buf);
7616 mapping[0].pszIssuerDomainPolicy = NULL;
7617 mapping[0].pszSubjectDomainPolicy = NULL;
7618 info.cPolicyMapping = 1;
7619 info.rgPolicyMapping = mapping;
7620 SetLastError(0xdeadbeef);
7621 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7622 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7623 ok(!ret && GetLastError() == E_INVALIDARG,
7624 "expected E_INVALIDARG, got %08x\n", GetLastError());
7625 mapping[0].pszIssuerDomainPolicy = oid1;
7626 mapping[0].pszSubjectDomainPolicy = oid2;
7627 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7628 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7629 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7630 if (ret)
7632 ok(size == sizeof(policyMappingWithOneMapping),
7633 "unexpected size %d\n", size);
7634 ok(!memcmp(buf, policyMappingWithOneMapping, size),
7635 "unexpected value\n");
7636 LocalFree(buf);
7638 mapping[1].pszIssuerDomainPolicy = oid3;
7639 mapping[1].pszSubjectDomainPolicy = oid4;
7640 info.cPolicyMapping = 2;
7641 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7642 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7643 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7644 if (ret)
7646 ok(size == sizeof(policyMappingWithTwoMappings),
7647 "unexpected size %d\n", size);
7648 ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7649 "unexpected value\n");
7650 LocalFree(buf);
7655 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7657 DWORD size, i;
7658 CERT_POLICY_MAPPINGS_INFO *info;
7659 BOOL ret;
7661 /* Each of the mapping OIDs is equivalent, so check with all of them */
7662 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7664 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7665 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7666 &info, &size);
7667 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7668 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7669 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7671 win_skip("no policy mappings support\n");
7672 return;
7674 if (ret)
7676 ok(info->cPolicyMapping == 0,
7677 "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7678 LocalFree(info);
7680 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7681 policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7682 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7683 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7684 if (ret)
7686 ok(info->cPolicyMapping == 1,
7687 "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7688 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7689 "unexpected issuer policy %s\n",
7690 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7691 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7692 "2.3.4"), "unexpected subject policy %s\n",
7693 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7694 LocalFree(info);
7696 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7697 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7698 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7699 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7700 if (ret)
7702 ok(info->cPolicyMapping == 2,
7703 "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7704 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7705 "unexpected issuer policy %s\n",
7706 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7707 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7708 "2.3.4"), "unexpected subject policy %s\n",
7709 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7710 ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7711 "unexpected issuer policy %s\n",
7712 info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7713 ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7714 "2.5.6"), "unexpected subject policy %s\n",
7715 info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7716 LocalFree(info);
7718 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7719 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7720 NULL, NULL, &size);
7721 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7722 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7723 if (info)
7725 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7726 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7727 NULL, info, &size);
7728 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7729 HeapFree(GetProcessHeap(), 0, info);
7734 static const BYTE policyConstraintsWithRequireExplicit[] = {
7735 0x30,0x03,0x80,0x01,0x00 };
7736 static const BYTE policyConstraintsWithInhibitMapping[] = {
7737 0x30,0x03,0x81,0x01,0x01 };
7738 static const BYTE policyConstraintsWithBoth[] = {
7739 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7741 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7743 CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7744 LPBYTE buf;
7745 DWORD size;
7746 BOOL ret;
7748 /* Even though RFC 5280 explicitly states CAs must not issue empty
7749 * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7751 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7752 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7753 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7754 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7755 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7757 win_skip("no policy constraints support\n");
7758 return;
7760 if (ret)
7762 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7763 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7764 "unexpected value\n");
7765 LocalFree(buf);
7767 /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7768 * is not, then a skip of 0 is encoded.
7770 info.fRequireExplicitPolicy = TRUE;
7771 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7772 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7773 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7774 if (ret)
7776 ok(size == sizeof(policyConstraintsWithRequireExplicit),
7777 "unexpected size %d\n", size);
7778 ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7779 sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7780 LocalFree(buf);
7782 /* With inhibit policy mapping */
7783 info.fRequireExplicitPolicy = FALSE;
7784 info.dwRequireExplicitPolicySkipCerts = 0;
7785 info.fInhibitPolicyMapping = TRUE;
7786 info.dwInhibitPolicyMappingSkipCerts = 1;
7787 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7788 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7789 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7790 if (ret)
7792 ok(size == sizeof(policyConstraintsWithInhibitMapping),
7793 "unexpected size %d\n", size);
7794 ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7795 sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7796 LocalFree(buf);
7798 /* And with both */
7799 info.fRequireExplicitPolicy = TRUE;
7800 info.dwRequireExplicitPolicySkipCerts = 1;
7801 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7802 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7803 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7804 if (ret)
7806 ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7807 size);
7808 ok(!memcmp(buf, policyConstraintsWithBoth,
7809 sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7810 LocalFree(buf);
7814 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7816 CERT_POLICY_CONSTRAINTS_INFO *info;
7817 DWORD size;
7818 BOOL ret;
7820 /* Again, even though CAs must not issue such constraints, they can be
7821 * decoded.
7823 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7824 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7825 &info, &size);
7826 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7827 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7828 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7830 win_skip("no policy mappings support\n");
7831 return;
7833 if (ret)
7835 ok(!info->fRequireExplicitPolicy,
7836 "expected require explicit = FALSE\n");
7837 ok(!info->fInhibitPolicyMapping,
7838 "expected implicit mapping = FALSE\n");
7839 LocalFree(info);
7841 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7842 policyConstraintsWithRequireExplicit,
7843 sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7844 NULL, &info, &size);
7845 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7846 if (ret)
7848 ok(info->fRequireExplicitPolicy,
7849 "expected require explicit = TRUE\n");
7850 ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7851 info->dwRequireExplicitPolicySkipCerts);
7852 ok(!info->fInhibitPolicyMapping,
7853 "expected implicit mapping = FALSE\n");
7854 LocalFree(info);
7856 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7857 policyConstraintsWithInhibitMapping,
7858 sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7859 NULL, &info, &size);
7860 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7861 if (ret)
7863 ok(!info->fRequireExplicitPolicy,
7864 "expected require explicit = FALSE\n");
7865 ok(info->fInhibitPolicyMapping,
7866 "expected implicit mapping = TRUE\n");
7867 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7868 info->dwInhibitPolicyMappingSkipCerts);
7869 LocalFree(info);
7871 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7872 policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7873 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7874 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7875 if (ret)
7877 ok(info->fRequireExplicitPolicy,
7878 "expected require explicit = TRUE\n");
7879 ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7880 info->dwRequireExplicitPolicySkipCerts);
7881 ok(info->fInhibitPolicyMapping,
7882 "expected implicit mapping = TRUE\n");
7883 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7884 info->dwInhibitPolicyMappingSkipCerts);
7885 LocalFree(info);
7889 /* Free *pInfo with HeapFree */
7890 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7892 BOOL ret;
7893 DWORD size = 0;
7894 HCRYPTKEY key;
7896 /* This crashes
7897 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7899 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7900 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7901 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7902 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7903 &size);
7904 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7905 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7906 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7907 NULL, &size);
7908 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7909 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7910 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7911 0, NULL, NULL, &size);
7912 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7913 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7914 /* Test with no key */
7915 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7916 0, NULL, NULL, &size);
7917 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7918 GetLastError());
7919 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7920 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7921 if (ret)
7923 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7924 NULL, 0, NULL, NULL, &size);
7925 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7926 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7927 if (*pInfo)
7929 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7930 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7931 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7932 GetLastError());
7933 if (ret)
7935 /* By default (we passed NULL as the OID) the OID is
7936 * szOID_RSA_RSA.
7938 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7939 "Expected %s, got %s\n", szOID_RSA_RSA,
7940 (*pInfo)->Algorithm.pszObjId);
7944 CryptDestroyKey(key);
7947 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7948 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7949 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7950 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7951 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7952 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7953 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7954 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7955 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7956 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7957 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7958 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7959 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7960 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7961 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7962 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7963 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7964 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7965 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7966 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7967 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7968 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7969 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7970 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7971 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7973 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7975 BOOL ret;
7976 HCRYPTKEY key;
7977 PCCERT_CONTEXT context;
7978 DWORD dwSize;
7979 ALG_ID ai;
7981 /* These crash
7982 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7983 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7984 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7985 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7986 NULL);
7988 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7989 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7990 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7991 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7992 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7993 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7994 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7995 &key);
7996 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7997 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7999 /* Export key with standard algorithm (CALG_RSA_KEYX) */
8000 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8001 &key);
8002 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8004 dwSize = sizeof(ai);
8005 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8006 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8007 if(ret)
8009 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8010 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8013 CryptDestroyKey(key);
8015 /* Repeat with forced algorithm */
8016 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8017 &key);
8018 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8020 dwSize = sizeof(ai);
8021 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8022 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8023 if(ret)
8025 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8026 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8029 CryptDestroyKey(key);
8031 /* Test importing a public key from a certificate context */
8032 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8033 sizeof(expiredCert));
8034 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8035 GetLastError());
8036 if (context)
8038 ok(!strcmp(szOID_RSA_RSA,
8039 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8040 "Expected %s, got %s\n", szOID_RSA_RSA,
8041 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8042 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8043 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8044 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8045 CryptDestroyKey(key);
8046 CertFreeCertificateContext(context);
8050 static const char cspName[] = "WineCryptTemp";
8052 static void testPortPublicKeyInfo(void)
8054 HCRYPTPROV csp;
8055 BOOL ret;
8056 PCERT_PUBLIC_KEY_INFO info = NULL;
8058 /* Just in case a previous run failed, delete this thing */
8059 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8060 CRYPT_DELETEKEYSET);
8061 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8062 CRYPT_NEWKEYSET);
8063 ok(ret,"CryptAcquireContextA failed\n");
8065 testExportPublicKey(csp, &info);
8066 testImportPublicKey(csp, info);
8068 HeapFree(GetProcessHeap(), 0, info);
8069 CryptReleaseContext(csp, 0);
8070 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8071 CRYPT_DELETEKEYSET);
8072 ok(ret,"CryptAcquireContextA failed\n");
8075 START_TEST(encode)
8077 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8078 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8079 HMODULE hCrypt32;
8080 DWORD i;
8082 hCrypt32 = GetModuleHandleA("crypt32.dll");
8083 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8084 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8085 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8087 win_skip("CryptDecodeObjectEx() is not available\n");
8088 return;
8091 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8093 test_encodeInt(encodings[i]);
8094 test_decodeInt(encodings[i]);
8095 test_encodeEnumerated(encodings[i]);
8096 test_decodeEnumerated(encodings[i]);
8097 test_encodeFiletime(encodings[i]);
8098 test_decodeFiletime(encodings[i]);
8099 test_encodeName(encodings[i]);
8100 test_decodeName(encodings[i]);
8101 test_encodeUnicodeName(encodings[i]);
8102 test_decodeUnicodeName(encodings[i]);
8103 test_encodeNameValue(encodings[i]);
8104 test_decodeNameValue(encodings[i]);
8105 test_encodeUnicodeNameValue(encodings[i]);
8106 test_decodeUnicodeNameValue(encodings[i]);
8107 test_encodeAltName(encodings[i]);
8108 test_decodeAltName(encodings[i]);
8109 test_encodeOctets(encodings[i]);
8110 test_decodeOctets(encodings[i]);
8111 test_encodeBits(encodings[i]);
8112 test_decodeBits(encodings[i]);
8113 test_encodeBasicConstraints(encodings[i]);
8114 test_decodeBasicConstraints(encodings[i]);
8115 test_encodeRsaPublicKey(encodings[i]);
8116 test_decodeRsaPublicKey(encodings[i]);
8117 test_encodeSequenceOfAny(encodings[i]);
8118 test_decodeSequenceOfAny(encodings[i]);
8119 test_encodeExtensions(encodings[i]);
8120 test_decodeExtensions(encodings[i]);
8121 test_encodePublicKeyInfo(encodings[i]);
8122 test_decodePublicKeyInfo(encodings[i]);
8123 test_encodeCertToBeSigned(encodings[i]);
8124 test_decodeCertToBeSigned(encodings[i]);
8125 test_encodeCert(encodings[i]);
8126 test_decodeCert(encodings[i]);
8127 test_encodeCRLDistPoints(encodings[i]);
8128 test_decodeCRLDistPoints(encodings[i]);
8129 test_encodeCRLIssuingDistPoint(encodings[i]);
8130 test_decodeCRLIssuingDistPoint(encodings[i]);
8131 test_encodeCRLToBeSigned(encodings[i]);
8132 test_decodeCRLToBeSigned(encodings[i]);
8133 test_encodeEnhancedKeyUsage(encodings[i]);
8134 test_decodeEnhancedKeyUsage(encodings[i]);
8135 test_encodeAuthorityKeyId(encodings[i]);
8136 test_decodeAuthorityKeyId(encodings[i]);
8137 test_encodeAuthorityKeyId2(encodings[i]);
8138 test_decodeAuthorityKeyId2(encodings[i]);
8139 test_encodeAuthorityInfoAccess(encodings[i]);
8140 test_decodeAuthorityInfoAccess(encodings[i]);
8141 test_encodeCTL(encodings[i]);
8142 test_decodeCTL(encodings[i]);
8143 test_encodePKCSContentInfo(encodings[i]);
8144 test_decodePKCSContentInfo(encodings[i]);
8145 test_encodePKCSAttribute(encodings[i]);
8146 test_decodePKCSAttribute(encodings[i]);
8147 test_encodePKCSAttributes(encodings[i]);
8148 test_decodePKCSAttributes(encodings[i]);
8149 test_encodePKCSSMimeCapabilities(encodings[i]);
8150 test_decodePKCSSMimeCapabilities(encodings[i]);
8151 test_encodePKCSSignerInfo(encodings[i]);
8152 test_decodePKCSSignerInfo(encodings[i]);
8153 test_encodeCMSSignerInfo(encodings[i]);
8154 test_decodeCMSSignerInfo(encodings[i]);
8155 test_encodeNameConstraints(encodings[i]);
8156 test_decodeNameConstraints(encodings[i]);
8157 test_encodePolicyQualifierUserNotice(encodings[i]);
8158 test_decodePolicyQualifierUserNotice(encodings[i]);
8159 test_encodeCertPolicies(encodings[i]);
8160 test_decodeCertPolicies(encodings[i]);
8161 test_encodeCertPolicyMappings(encodings[i]);
8162 test_decodeCertPolicyMappings(encodings[i]);
8163 test_encodeCertPolicyConstraints(encodings[i]);
8164 test_decodeCertPolicyConstraints(encodings[i]);
8166 testPortPublicKeyInfo();