push 378fe7a60681a28e8b22f62dcfe122d585b92570
[wine/hacks.git] / dlls / crypt32 / tests / encode.c
blob5c681b638ccd8520e3e97183b7b680f6e5b44606
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
850 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851 ok(!memcmp(buf, encodedTwoRDNs, size),
852 "Unexpected value for re-endoded two RDN array\n");
853 LocalFree(buf);
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 (buf)
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 (buf)
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 (buf)
974 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975 ok(!memcmp(buf, encodedTwoRDNs, size),
976 "Unexpected value for re-endoded two RDN array\n");
977 LocalFree(buf);
979 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980 rdn.cRDNAttr = 1;
981 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985 if (buf)
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 "String type %d: unexpected data size, got %d, expected %d\n",
1008 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009 if (got->Value.cbData && got->Value.pbData)
1010 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011 min(got->Value.cbData, expected->Value.cbData)),
1012 "String type %d: unexpected value\n", expected->dwValueType);
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016 const CERT_RDN_ATTR *got)
1018 if (expected->pszObjId && strlen(expected->pszObjId))
1020 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021 expected->pszObjId);
1022 if (got->pszObjId)
1024 ok(!strcmp(got->pszObjId, expected->pszObjId),
1025 "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026 expected->pszObjId);
1029 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030 (const CERT_NAME_VALUE *)&got->dwValueType);
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1035 ok(got->cRDNAttr == expected->cRDNAttr,
1036 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037 if (got->cRDNAttr)
1039 DWORD i;
1041 for (i = 0; i < got->cRDNAttr; i++)
1042 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047 const CERT_NAME_INFO *got)
1049 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050 expected->cRDN, got->cRDN);
1051 if (got->cRDN)
1053 DWORD i;
1055 for (i = 0; i < got->cRDN; i++)
1056 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1066 static void test_decodeName(DWORD dwEncoding)
1068 BYTE *buf = NULL;
1069 DWORD bufSize = 0;
1070 BOOL ret;
1071 CERT_RDN rdn;
1072 CERT_NAME_INFO info = { 1, &rdn };
1074 /* test empty name */
1075 bufSize = 0;
1076 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077 emptySequence[1] + 2,
1078 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079 &buf, &bufSize);
1080 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
1082 * decoder works the same way, so only test the count.
1084 if (buf)
1086 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088 "Expected 0 RDNs in empty info, got %d\n",
1089 ((CERT_NAME_INFO *)buf)->cRDN);
1090 LocalFree(buf);
1092 /* test empty name with indefinite-length encoding */
1093 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094 sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095 &buf, &bufSize);
1096 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097 if (ret)
1099 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101 "Expected 0 RDNs in empty info, got %d\n",
1102 ((CERT_NAME_INFO *)buf)->cRDN);
1103 LocalFree(buf);
1105 /* test empty RDN */
1106 bufSize = 0;
1107 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108 emptyRDNs[1] + 2,
1109 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110 &buf, &bufSize);
1111 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112 if (buf)
1114 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1116 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118 "Got unexpected value for empty RDN\n");
1119 LocalFree(buf);
1121 /* test two RDN attrs */
1122 bufSize = 0;
1123 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124 twoRDNs[1] + 2,
1125 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126 &buf, &bufSize);
1127 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128 if (buf)
1130 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1131 oid_common_name[] = szOID_COMMON_NAME;
1133 CERT_RDN_ATTR attrs[] = {
1134 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135 (BYTE *)surName } },
1136 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137 (BYTE *)commonName } },
1140 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141 rdn.rgRDNAttr = attrs;
1142 compareNames(&info, (CERT_NAME_INFO *)buf);
1143 LocalFree(buf);
1145 /* test that two RDN attrs with extra bytes succeeds */
1146 bufSize = 0;
1147 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150 /* And, a slightly more complicated name */
1151 buf = NULL;
1152 bufSize = 0;
1153 ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156 if (ret)
1158 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159 rdn.rgRDNAttr = decodedRdnAttrs;
1160 compareNames(&info, (CERT_NAME_INFO *)buf);
1161 LocalFree(buf);
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1167 BYTE *buf = NULL;
1168 DWORD bufSize = 0;
1169 BOOL ret;
1170 CERT_RDN rdn;
1171 CERT_NAME_INFO info = { 1, &rdn };
1173 /* test empty name */
1174 bufSize = 0;
1175 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176 emptySequence[1] + 2,
1177 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178 &buf, &bufSize);
1179 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180 if (buf)
1182 ok(bufSize == sizeof(CERT_NAME_INFO),
1183 "Got wrong bufSize %d\n", bufSize);
1184 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185 "Expected 0 RDNs in empty info, got %d\n",
1186 ((CERT_NAME_INFO *)buf)->cRDN);
1187 LocalFree(buf);
1189 /* test empty RDN */
1190 bufSize = 0;
1191 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192 emptyRDNs[1] + 2,
1193 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194 &buf, &bufSize);
1195 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196 if (buf)
1198 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1200 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202 "Got unexpected value for empty RDN\n");
1203 LocalFree(buf);
1205 /* test two RDN attrs */
1206 bufSize = 0;
1207 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208 sizeof(twoRDNsNoNull),
1209 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210 &buf, &bufSize);
1211 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212 if (buf)
1214 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1215 oid_common_name[] = szOID_COMMON_NAME;
1217 CERT_RDN_ATTR attrs[] = {
1218 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1224 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225 rdn.rgRDNAttr = attrs;
1226 compareNames(&info, (CERT_NAME_INFO *)buf);
1227 LocalFree(buf);
1231 struct EncodedNameValue
1233 CERT_NAME_VALUE value;
1234 const BYTE *encoded;
1235 DWORD encodedSize;
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1268 static struct EncodedNameValue nameValues[] = {
1269 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270 octetCommonNameValue, sizeof(octetCommonNameValue) },
1271 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272 numericCommonNameValue, sizeof(numericCommonNameValue) },
1273 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274 printableCommonNameValue, sizeof(printableCommonNameValue) },
1275 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276 t61CommonNameValue, sizeof(t61CommonNameValue) },
1277 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1279 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1281 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1283 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1285 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286 generalCommonNameValue, sizeof(generalCommonNameValue) },
1287 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1288 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1289 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1290 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1291 /* The following tests succeed under Windows, but really should fail,
1292 * they contain characters that are illegal for the encoding. I'm
1293 * including them to justify my lazy encoding.
1295 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1296 sizeof(bin42) },
1297 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1298 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1299 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1300 bin44, sizeof(bin44) },
1303 static void test_encodeNameValue(DWORD dwEncoding)
1305 BYTE *buf = NULL;
1306 DWORD size = 0, i;
1307 BOOL ret;
1308 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1310 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1311 value.Value.pbData = printableCommonNameValue;
1312 value.Value.cbData = sizeof(printableCommonNameValue);
1313 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1314 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1315 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1316 if (buf)
1318 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1319 size);
1320 ok(!memcmp(buf, printableCommonNameValue, size),
1321 "Unexpected encoding\n");
1322 LocalFree(buf);
1324 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1326 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1327 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1328 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1329 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1330 nameValues[i].value.dwValueType, GetLastError());
1331 if (ret)
1333 ok(size == nameValues[i].encodedSize,
1334 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1335 ok(!memcmp(buf, nameValues[i].encoded, size),
1336 "Got unexpected encoding\n");
1337 LocalFree(buf);
1342 static void test_decodeNameValue(DWORD dwEncoding)
1344 int i;
1345 BYTE *buf = NULL;
1346 DWORD bufSize = 0;
1347 BOOL ret;
1349 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1351 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1352 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1353 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1354 &buf, &bufSize);
1355 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1356 nameValues[i].value.dwValueType, GetLastError());
1357 if (ret)
1359 compareNameValues(&nameValues[i].value,
1360 (const CERT_NAME_VALUE *)buf);
1361 LocalFree(buf);
1366 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1367 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1368 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1369 'h','q','.','o','r','g',0 };
1370 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1371 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1372 0x6f, 0x72, 0x67 };
1373 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1374 0x575b, 0 };
1375 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1376 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1377 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1378 static const BYTE localhost[] = { 127, 0, 0, 1 };
1379 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1380 0x01 };
1381 static const unsigned char encodedCommonName[] = {
1382 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1383 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1384 static const BYTE encodedDirectoryName[] = {
1385 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1386 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1388 static void test_encodeAltName(DWORD dwEncoding)
1390 CERT_ALT_NAME_INFO info = { 0 };
1391 CERT_ALT_NAME_ENTRY entry = { 0 };
1392 BYTE *buf = NULL;
1393 DWORD size = 0;
1394 BOOL ret;
1395 char oid[] = "1.2.3";
1397 /* Test with empty info */
1398 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1399 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1400 if (buf)
1402 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1403 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1404 LocalFree(buf);
1406 /* Test with an empty entry */
1407 info.cAltEntry = 1;
1408 info.rgAltEntry = &entry;
1409 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1411 ok(!ret && GetLastError() == E_INVALIDARG,
1412 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1413 /* Test with an empty pointer */
1414 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1415 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1416 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1417 if (buf)
1419 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1420 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1421 LocalFree(buf);
1423 /* Test with a real URL */
1424 U(entry).pwszURL = (LPWSTR)url;
1425 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1426 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1427 if (buf)
1429 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1430 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1431 LocalFree(buf);
1433 /* Now with the URL containing an invalid IA5 char */
1434 U(entry).pwszURL = (LPWSTR)nihongoURL;
1435 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1438 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1439 /* The first invalid character is at index 7 */
1440 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1441 "Expected invalid char at index 7, got %d\n",
1442 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1443 /* Now with the URL missing a scheme */
1444 U(entry).pwszURL = (LPWSTR)dnsName;
1445 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1446 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1447 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1448 if (buf)
1450 /* This succeeds, but it shouldn't, so don't worry about conforming */
1451 LocalFree(buf);
1453 /* Now with a DNS name */
1454 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1455 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1456 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1457 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1458 if (buf)
1460 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1461 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1462 LocalFree(buf);
1464 /* Test with an IP address */
1465 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1466 U(entry).IPAddress.cbData = sizeof(localhost);
1467 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1468 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1469 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1470 if (buf)
1472 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1473 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1474 LocalFree(buf);
1476 /* Test with OID */
1477 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1478 U(entry).pszRegisteredID = oid;
1479 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1480 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1481 if (buf)
1483 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1484 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1485 LocalFree(buf);
1487 /* Test with directory name */
1488 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1489 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1490 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1491 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1492 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1493 if (buf)
1495 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1496 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1497 LocalFree(buf);
1501 static void test_decodeAltName(DWORD dwEncoding)
1503 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1504 0x00, 0x00, 0x01 };
1505 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1506 0x01 };
1507 BOOL ret;
1508 BYTE *buf = NULL;
1509 DWORD bufSize = 0;
1510 CERT_ALT_NAME_INFO *info;
1512 /* Test some bogus ones first */
1513 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1514 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1515 NULL, &buf, &bufSize);
1516 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1517 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1518 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1519 GetLastError());
1520 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1521 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1522 &bufSize);
1523 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1524 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1525 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1526 GetLastError());
1527 /* Now expected cases */
1528 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1529 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1530 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1531 if (buf)
1533 info = (CERT_ALT_NAME_INFO *)buf;
1535 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1536 info->cAltEntry);
1537 LocalFree(buf);
1539 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1540 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1541 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1542 if (buf)
1544 info = (CERT_ALT_NAME_INFO *)buf;
1546 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1547 info->cAltEntry);
1548 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1549 "Expected CERT_ALT_NAME_URL, got %d\n",
1550 info->rgAltEntry[0].dwAltNameChoice);
1551 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1552 "Expected empty URL\n");
1553 LocalFree(buf);
1555 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1556 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1557 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1558 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1559 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1560 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1561 if (buf)
1563 info = (CERT_ALT_NAME_INFO *)buf;
1565 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1566 info->cAltEntry);
1567 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1568 "Expected CERT_ALT_NAME_URL, got %d\n",
1569 info->rgAltEntry[0].dwAltNameChoice);
1570 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1571 LocalFree(buf);
1573 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1574 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1575 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1576 if (buf)
1578 info = (CERT_ALT_NAME_INFO *)buf;
1580 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1581 info->cAltEntry);
1582 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1583 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1584 info->rgAltEntry[0].dwAltNameChoice);
1585 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1586 "Unexpected DNS name\n");
1587 LocalFree(buf);
1589 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1590 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1591 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1592 if (buf)
1594 info = (CERT_ALT_NAME_INFO *)buf;
1596 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1597 info->cAltEntry);
1598 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1599 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1600 info->rgAltEntry[0].dwAltNameChoice);
1601 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1602 "Unexpected IP address length %d\n",
1603 U(info->rgAltEntry[0]).IPAddress.cbData);
1604 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1605 sizeof(localhost)), "Unexpected IP address value\n");
1606 LocalFree(buf);
1608 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1609 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611 if (buf)
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_REGISTERED_ID,
1618 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1619 info->rgAltEntry[0].dwAltNameChoice);
1620 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1621 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1622 LocalFree(buf);
1624 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625 encodedDirectoryName, sizeof(encodedDirectoryName),
1626 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1627 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628 if (buf)
1630 info = (CERT_ALT_NAME_INFO *)buf;
1632 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633 info->cAltEntry);
1634 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1635 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1636 info->rgAltEntry[0].dwAltNameChoice);
1637 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1638 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1639 U(info->rgAltEntry[0]).DirectoryName.cbData);
1640 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1641 encodedCommonName, sizeof(encodedCommonName)),
1642 "Unexpected directory name value\n");
1643 LocalFree(buf);
1647 struct UnicodeExpectedError
1649 DWORD valueType;
1650 LPCWSTR str;
1651 DWORD errorIndex;
1652 DWORD error;
1655 static const WCHAR oneW[] = { '1',0 };
1656 static const WCHAR aW[] = { 'a',0 };
1657 static const WCHAR quoteW[] = { '"', 0 };
1659 static struct UnicodeExpectedError unicodeErrors[] = {
1660 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1661 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1662 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1663 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1664 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1665 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1668 struct UnicodeExpectedResult
1670 DWORD valueType;
1671 LPCWSTR str;
1672 CRYPT_DATA_BLOB encoded;
1675 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1676 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1677 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1678 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1679 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1680 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1681 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1682 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1683 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1684 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1685 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1686 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1687 0x5b };
1688 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1689 0x6f,0x5b };
1690 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1691 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1692 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1693 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1695 static struct UnicodeExpectedResult unicodeResults[] = {
1696 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1697 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1698 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1699 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1700 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1701 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1702 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1703 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1704 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1705 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1706 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1707 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1708 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1711 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1712 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1713 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1716 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1718 BYTE *buf = NULL;
1719 DWORD size = 0, i;
1720 BOOL ret;
1721 CERT_NAME_VALUE value;
1723 if (0)
1725 /* Crashes on win9x */
1726 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1727 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1728 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1729 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1731 /* Have to have a string of some sort */
1732 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1733 value.Value.pbData = NULL;
1734 value.Value.cbData = 0;
1735 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1737 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1740 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1742 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744 value.dwValueType = CERT_RDN_ANY_TYPE;
1745 value.Value.pbData = (LPBYTE)oneW;
1746 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1747 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1748 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1749 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1750 value.Value.cbData = sizeof(oneW);
1751 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1752 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1753 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1754 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1755 /* An encoded string with specified length isn't good enough either */
1756 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1757 value.Value.pbData = oneUniversal;
1758 value.Value.cbData = sizeof(oneUniversal);
1759 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1760 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1761 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1762 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1763 /* More failure checking */
1764 value.Value.cbData = 0;
1765 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1767 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1768 value.dwValueType = unicodeErrors[i].valueType;
1769 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1770 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1771 ok(!ret && GetLastError() == unicodeErrors[i].error,
1772 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1773 unicodeErrors[i].error, GetLastError());
1774 ok(size == unicodeErrors[i].errorIndex,
1775 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1776 size);
1778 /* cbData can be zero if the string is NULL-terminated */
1779 value.Value.cbData = 0;
1780 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1782 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1783 value.dwValueType = unicodeResults[i].valueType;
1784 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1785 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1786 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1787 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1788 if (buf)
1790 ok(size == unicodeResults[i].encoded.cbData,
1791 "Value type %d: expected size %d, got %d\n",
1792 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1793 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1794 "Value type %d: unexpected value\n", value.dwValueType);
1795 LocalFree(buf);
1798 /* These "encode," but they do so by truncating each unicode character
1799 * rather than properly encoding it. Kept separate from the proper results,
1800 * because the encoded forms won't decode to their original strings.
1802 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1804 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1805 value.dwValueType = unicodeWeirdness[i].valueType;
1806 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1807 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1808 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1809 if (buf)
1811 ok(size == unicodeWeirdness[i].encoded.cbData,
1812 "Value type %d: expected size %d, got %d\n",
1813 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1814 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1815 "Value type %d: unexpected value\n", value.dwValueType);
1816 LocalFree(buf);
1821 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1823 if (n <= 0) return 0;
1824 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1825 return *str1 - *str2;
1828 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1830 DWORD i;
1832 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1834 BYTE *buf = NULL;
1835 BOOL ret;
1836 DWORD size = 0;
1838 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1839 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1840 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1841 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1842 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1843 if (ret && buf)
1845 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1847 ok(value->dwValueType == unicodeResults[i].valueType,
1848 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1849 value->dwValueType);
1850 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1851 value->Value.cbData / sizeof(WCHAR)),
1852 "Unexpected decoded value for index %d (value type %d)\n", i,
1853 unicodeResults[i].valueType);
1854 LocalFree(buf);
1859 struct encodedOctets
1861 const BYTE *val;
1862 const BYTE *encoded;
1865 static const unsigned char bin46[] = { 'h','i',0 };
1866 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1867 static const unsigned char bin48[] = {
1868 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin49[] = {
1870 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1871 static const unsigned char bin50[] = { 0 };
1872 static const unsigned char bin51[] = { 0x04,0x00,0 };
1874 static const struct encodedOctets octets[] = {
1875 { bin46, bin47 },
1876 { bin48, bin49 },
1877 { bin50, bin51 },
1880 static void test_encodeOctets(DWORD dwEncoding)
1882 CRYPT_DATA_BLOB blob;
1883 DWORD i;
1885 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1887 BYTE *buf = NULL;
1888 BOOL ret;
1889 DWORD bufSize = 0;
1891 blob.cbData = strlen((const char*)octets[i].val);
1892 blob.pbData = (BYTE*)octets[i].val;
1893 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1894 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1895 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1896 if (buf)
1898 ok(buf[0] == 4,
1899 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1900 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1901 buf[1], octets[i].encoded[1]);
1902 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1903 octets[i].encoded[1] + 1), "Got unexpected value\n");
1904 LocalFree(buf);
1909 static void test_decodeOctets(DWORD dwEncoding)
1911 DWORD i;
1913 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1915 BYTE *buf = NULL;
1916 BOOL ret;
1917 DWORD bufSize = 0;
1919 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1920 octets[i].encoded, octets[i].encoded[1] + 2,
1921 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1922 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1923 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1924 "Expected size >= %d, got %d\n",
1925 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1926 ok(buf != NULL, "Expected allocated buffer\n");
1927 if (buf)
1929 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1931 if (blob->cbData)
1932 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1933 "Unexpected value\n");
1934 LocalFree(buf);
1939 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1941 struct encodedBits
1943 DWORD cUnusedBits;
1944 const BYTE *encoded;
1945 DWORD cbDecoded;
1946 const BYTE *decoded;
1949 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1950 static const unsigned char bin53[] = { 0xff,0xff };
1951 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1952 static const unsigned char bin55[] = { 0xff,0xfe };
1953 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1954 static const unsigned char bin57[] = { 0xfe };
1955 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1957 static const struct encodedBits bits[] = {
1958 /* normal test cases */
1959 { 0, bin52, 2, bin53 },
1960 { 1, bin54, 2, bin55 },
1961 /* strange test case, showing cUnusedBits >= 8 is allowed */
1962 { 9, bin56, 1, bin57 },
1963 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1964 { 17, bin58, 0, NULL },
1967 static void test_encodeBits(DWORD dwEncoding)
1969 DWORD i;
1971 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1973 CRYPT_BIT_BLOB blob;
1974 BOOL ret;
1975 BYTE *buf = NULL;
1976 DWORD bufSize = 0;
1978 blob.cbData = sizeof(bytesToEncode);
1979 blob.pbData = (BYTE *)bytesToEncode;
1980 blob.cUnusedBits = bits[i].cUnusedBits;
1981 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1982 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1983 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1984 if (buf)
1986 ok(bufSize == bits[i].encoded[1] + 2,
1987 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
1988 bits[i].encoded[1] + 2);
1989 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1990 "%d: Unexpected value\n", i);
1991 LocalFree(buf);
1996 static void test_decodeBits(DWORD dwEncoding)
1998 static const BYTE ber[] = "\x03\x02\x01\xff";
1999 static const BYTE berDecoded = 0xfe;
2000 DWORD i;
2001 BOOL ret;
2002 BYTE *buf = NULL;
2003 DWORD bufSize = 0;
2005 /* normal cases */
2006 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2008 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2009 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2010 &bufSize);
2011 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2012 if (buf)
2014 CRYPT_BIT_BLOB *blob;
2016 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2017 "Got unexpected size %d\n", bufSize);
2018 blob = (CRYPT_BIT_BLOB *)buf;
2019 ok(blob->cbData == bits[i].cbDecoded,
2020 "Got unexpected length %d, expected %d\n", blob->cbData,
2021 bits[i].cbDecoded);
2022 if (blob->cbData && bits[i].cbDecoded)
2023 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2024 "Unexpected value\n");
2025 LocalFree(buf);
2028 /* special case: check that something that's valid in BER but not in DER
2029 * decodes successfully
2031 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2032 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2033 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2034 if (buf)
2036 CRYPT_BIT_BLOB *blob;
2038 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2039 "Got unexpected size %d\n", bufSize);
2040 blob = (CRYPT_BIT_BLOB *)buf;
2041 ok(blob->cbData == sizeof(berDecoded),
2042 "Got unexpected length %d\n", blob->cbData);
2043 if (blob->cbData)
2044 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2045 LocalFree(buf);
2049 struct Constraints2
2051 CERT_BASIC_CONSTRAINTS2_INFO info;
2052 const BYTE *encoded;
2055 static const unsigned char bin59[] = { 0x30,0x00 };
2056 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2057 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2058 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2059 static const struct Constraints2 constraints2[] = {
2060 /* empty constraints */
2061 { { FALSE, FALSE, 0}, bin59 },
2062 /* can be a CA */
2063 { { TRUE, FALSE, 0}, bin60 },
2064 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2065 * but that's not the case
2067 { { FALSE, TRUE, 0}, bin61 },
2068 /* can be a CA and has path length constraints set */
2069 { { TRUE, TRUE, 1}, bin62 },
2072 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2073 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2074 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2075 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2076 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2077 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2078 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2079 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2080 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2081 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2083 static void test_encodeBasicConstraints(DWORD dwEncoding)
2085 DWORD i, bufSize = 0;
2086 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2087 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2088 (LPBYTE)encodedDomainName };
2089 BOOL ret;
2090 BYTE *buf = NULL;
2092 /* First test with the simpler info2 */
2093 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2095 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2096 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2097 &bufSize);
2098 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2099 if (buf)
2101 ok(bufSize == constraints2[i].encoded[1] + 2,
2102 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2103 bufSize);
2104 ok(!memcmp(buf, constraints2[i].encoded,
2105 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2106 LocalFree(buf);
2109 /* Now test with more complex basic constraints */
2110 info.SubjectType.cbData = 0;
2111 info.fPathLenConstraint = FALSE;
2112 info.cSubtreesConstraint = 0;
2113 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2114 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2115 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2116 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2117 if (buf)
2119 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2120 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2121 "Unexpected value\n");
2122 LocalFree(buf);
2124 /* None of the certs I examined had any subtree constraint, but I test one
2125 * anyway just in case.
2127 info.cSubtreesConstraint = 1;
2128 info.rgSubtreesConstraint = &nameBlob;
2129 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2130 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2131 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2132 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2133 if (buf)
2135 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2136 ok(!memcmp(buf, constraintWithDomainName,
2137 sizeof(constraintWithDomainName)), "Unexpected value\n");
2138 LocalFree(buf);
2140 /* FIXME: test encoding with subject type. */
2143 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2145 static void test_decodeBasicConstraints(DWORD dwEncoding)
2147 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2148 0xff };
2149 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2150 DWORD i;
2151 BOOL ret;
2152 BYTE *buf = NULL;
2153 DWORD bufSize = 0;
2155 /* First test with simpler info2 */
2156 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2158 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2159 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2160 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2161 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2162 GetLastError());
2163 if (buf)
2165 CERT_BASIC_CONSTRAINTS2_INFO *info =
2166 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2168 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2169 "Unexpected value for item %d\n", i);
2170 LocalFree(buf);
2173 /* Check with the order of encoded elements inverted */
2174 buf = (PBYTE)1;
2175 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2176 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2177 &bufSize);
2178 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2179 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2180 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2181 GetLastError());
2182 ok(!buf, "Expected buf to be set to NULL\n");
2183 /* Check with a non-DER bool */
2184 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2185 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2186 &buf, &bufSize);
2187 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2188 if (buf)
2190 CERT_BASIC_CONSTRAINTS2_INFO *info =
2191 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2193 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2194 LocalFree(buf);
2196 /* Check with a non-basic constraints value */
2197 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2198 encodedCommonName, encodedCommonName[1] + 2,
2199 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2200 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2201 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2202 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2203 GetLastError());
2204 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2205 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2206 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2207 &buf, &bufSize);
2208 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2209 if (buf)
2211 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2213 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2214 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2215 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2216 LocalFree(buf);
2218 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2219 constraintWithDomainName, sizeof(constraintWithDomainName),
2220 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2221 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2222 if (buf)
2224 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2226 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2227 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2228 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2229 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2231 ok(info->rgSubtreesConstraint[0].cbData ==
2232 sizeof(encodedDomainName), "Wrong size %d\n",
2233 info->rgSubtreesConstraint[0].cbData);
2234 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2235 sizeof(encodedDomainName)), "Unexpected value\n");
2237 LocalFree(buf);
2241 /* These are terrible public keys of course, I'm just testing encoding */
2242 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2243 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2244 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2245 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2246 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2248 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2249 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2251 struct EncodedRSAPubKey
2253 const BYTE *modulus;
2254 size_t modulusLen;
2255 const BYTE *encoded;
2256 size_t decodedModulusLen;
2259 struct EncodedRSAPubKey rsaPubKeys[] = {
2260 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2261 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2262 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2263 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2266 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2268 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2269 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2270 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2271 BOOL ret;
2272 BYTE *buf = NULL;
2273 DWORD bufSize = 0, i;
2275 /* Try with a bogus blob type */
2276 hdr->bType = 2;
2277 hdr->bVersion = CUR_BLOB_VERSION;
2278 hdr->reserved = 0;
2279 hdr->aiKeyAlg = CALG_RSA_KEYX;
2280 rsaPubKey->magic = 0x31415352;
2281 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2282 rsaPubKey->pubexp = 65537;
2283 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2284 sizeof(modulus1));
2286 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2287 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2288 ok(!ret && GetLastError() == E_INVALIDARG,
2289 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2290 /* Now with a bogus reserved field */
2291 hdr->bType = PUBLICKEYBLOB;
2292 hdr->reserved = 1;
2293 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2294 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2295 if (buf)
2297 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2298 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2299 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2300 LocalFree(buf);
2302 /* Now with a bogus blob version */
2303 hdr->reserved = 0;
2304 hdr->bVersion = 0;
2305 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2306 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2307 if (buf)
2309 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2310 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2311 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2312 LocalFree(buf);
2314 /* And with a bogus alg ID */
2315 hdr->bVersion = CUR_BLOB_VERSION;
2316 hdr->aiKeyAlg = CALG_DES;
2317 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2318 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2319 if (buf)
2321 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2322 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2323 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2324 LocalFree(buf);
2326 /* Check a couple of RSA-related OIDs */
2327 hdr->aiKeyAlg = CALG_RSA_KEYX;
2328 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2329 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2330 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2331 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2332 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2333 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2334 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2335 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2336 /* Finally, all valid */
2337 hdr->aiKeyAlg = CALG_RSA_KEYX;
2338 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2340 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2341 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2342 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2343 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2344 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2345 if (buf)
2347 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2348 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2349 bufSize);
2350 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2351 "Unexpected value\n");
2352 LocalFree(buf);
2357 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2359 DWORD i;
2360 LPBYTE buf = NULL;
2361 DWORD bufSize = 0;
2362 BOOL ret;
2364 /* Try with a bad length */
2365 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2366 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2367 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2368 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2369 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2370 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2371 GetLastError());
2372 /* Try with a couple of RSA-related OIDs */
2373 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2374 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2375 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2376 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2377 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2378 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2379 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2380 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2381 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2382 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2383 /* Now try success cases */
2384 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2386 bufSize = 0;
2387 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2388 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2389 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2390 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2391 if (buf)
2393 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2394 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2396 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2397 rsaPubKeys[i].decodedModulusLen,
2398 "Wrong size %d\n", bufSize);
2399 ok(hdr->bType == PUBLICKEYBLOB,
2400 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2401 hdr->bType);
2402 ok(hdr->bVersion == CUR_BLOB_VERSION,
2403 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2404 CUR_BLOB_VERSION, hdr->bVersion);
2405 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2406 hdr->reserved);
2407 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2408 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2409 ok(rsaPubKey->magic == 0x31415352,
2410 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2411 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2412 "Wrong bit len %d\n", rsaPubKey->bitlen);
2413 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2414 rsaPubKey->pubexp);
2415 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2416 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2417 "Unexpected modulus\n");
2418 LocalFree(buf);
2423 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2424 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2425 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2427 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2428 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2429 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2430 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2432 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2434 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2435 CRYPT_SEQUENCE_OF_ANY seq;
2436 DWORD i;
2437 BOOL ret;
2438 BYTE *buf = NULL;
2439 DWORD bufSize = 0;
2441 /* Encode a homogeneous sequence */
2442 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2444 blobs[i].cbData = ints[i].encoded[1] + 2;
2445 blobs[i].pbData = (BYTE *)ints[i].encoded;
2447 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2448 seq.rgValue = blobs;
2450 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2451 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2452 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2453 if (buf)
2455 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2456 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2457 LocalFree(buf);
2459 /* Change the type of the first element in the sequence, and give it
2460 * another go
2462 blobs[0].cbData = times[0].encodedTime[1] + 2;
2463 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2464 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2465 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2466 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2467 if (buf)
2469 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2470 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2471 "Unexpected value\n");
2472 LocalFree(buf);
2476 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2478 BOOL ret;
2479 BYTE *buf = NULL;
2480 DWORD bufSize = 0;
2482 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2483 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2484 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2485 if (buf)
2487 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2488 DWORD i;
2490 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2491 "Wrong elements %d\n", seq->cValue);
2492 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2494 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2495 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2496 seq->rgValue[i].cbData);
2497 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2498 ints[i].encoded[1] + 2), "Unexpected value\n");
2500 LocalFree(buf);
2502 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2503 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2504 &bufSize);
2505 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2506 if (buf)
2508 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2510 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2511 "Wrong elements %d\n", seq->cValue);
2512 /* Just check the first element since it's all that changed */
2513 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2514 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2515 seq->rgValue[0].cbData);
2516 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2517 times[0].encodedTime[1] + 2), "Unexpected value\n");
2518 LocalFree(buf);
2522 struct encodedExtensions
2524 CERT_EXTENSIONS exts;
2525 const BYTE *encoded;
2528 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2529 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2530 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2531 static CERT_EXTENSION criticalExt =
2532 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2533 static CERT_EXTENSION nonCriticalExt =
2534 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2535 static CHAR oid_short[] = "1.1";
2536 static CERT_EXTENSION extWithShortOid =
2537 { oid_short, FALSE, { 0, NULL } };
2539 static const BYTE ext0[] = { 0x30,0x00 };
2540 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2541 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2543 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2544 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2546 static const struct encodedExtensions exts[] = {
2547 { { 0, NULL }, ext0 },
2548 { { 1, &criticalExt }, ext1 },
2549 { { 1, &nonCriticalExt }, ext2 },
2550 { { 1, &extWithShortOid }, ext3 }
2553 static void test_encodeExtensions(DWORD dwEncoding)
2555 DWORD i;
2557 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2559 BOOL ret;
2560 BYTE *buf = NULL;
2561 DWORD bufSize = 0;
2563 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2564 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2565 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2566 if (buf)
2568 ok(bufSize == exts[i].encoded[1] + 2,
2569 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2570 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2571 "Unexpected value\n");
2572 LocalFree(buf);
2577 static void test_decodeExtensions(DWORD dwEncoding)
2579 DWORD i;
2581 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2583 BOOL ret;
2584 BYTE *buf = NULL;
2585 DWORD bufSize = 0;
2587 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2588 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2589 NULL, &buf, &bufSize);
2590 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2591 if (buf)
2593 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2594 DWORD j;
2596 ok(ext->cExtension == exts[i].exts.cExtension,
2597 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2598 ext->cExtension);
2599 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2601 ok(!strcmp(ext->rgExtension[j].pszObjId,
2602 exts[i].exts.rgExtension[j].pszObjId),
2603 "Expected OID %s, got %s\n",
2604 exts[i].exts.rgExtension[j].pszObjId,
2605 ext->rgExtension[j].pszObjId);
2606 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2607 exts[i].exts.rgExtension[j].Value.pbData,
2608 exts[i].exts.rgExtension[j].Value.cbData),
2609 "Unexpected value\n");
2611 LocalFree(buf);
2616 /* MS encodes public key info with a NULL if the algorithm identifier's
2617 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2618 * it encodes them by omitting the algorithm parameters. This latter approach
2619 * seems more correct, so accept either form.
2621 struct encodedPublicKey
2623 CERT_PUBLIC_KEY_INFO info;
2624 const BYTE *encoded;
2625 const BYTE *encodedNoNull;
2626 CERT_PUBLIC_KEY_INFO decoded;
2629 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2630 0xe, 0xf };
2631 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2633 static const unsigned char bin64[] = {
2634 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2635 static const unsigned char bin65[] = {
2636 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2637 static const unsigned char bin66[] = {
2638 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2639 static const unsigned char bin67[] = {
2640 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2641 static const unsigned char bin68[] = {
2642 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2643 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2644 static const unsigned char bin69[] = {
2645 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2646 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2647 static const unsigned char bin70[] = {
2648 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2649 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2650 0x0f};
2651 static const unsigned char bin71[] = {
2652 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2653 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2654 0x0f};
2655 static unsigned char bin72[] = { 0x05,0x00};
2657 static CHAR oid_bogus[] = "1.2.3",
2658 oid_rsa[] = szOID_RSA;
2660 static const struct encodedPublicKey pubKeys[] = {
2661 /* with a bogus OID */
2662 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2663 bin64, bin65,
2664 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2665 /* some normal keys */
2666 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2667 bin66, bin67,
2668 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2669 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2670 bin68, bin69,
2671 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2672 /* with add'l parameters--note they must be DER-encoded */
2673 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2674 (BYTE *)aKey, 0 } },
2675 bin70, bin71,
2676 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2677 (BYTE *)aKey, 0 } } },
2680 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2682 DWORD i;
2684 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2686 BOOL ret;
2687 BYTE *buf = NULL;
2688 DWORD bufSize = 0;
2690 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2691 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2692 &bufSize);
2693 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2694 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2695 if (buf)
2697 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2698 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2699 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2700 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2701 if (bufSize == pubKeys[i].encoded[1] + 2)
2702 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2703 "Unexpected value\n");
2704 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2705 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2706 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2707 LocalFree(buf);
2712 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2713 const CERT_PUBLIC_KEY_INFO *got)
2715 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2716 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2717 got->Algorithm.pszObjId);
2718 ok(expected->Algorithm.Parameters.cbData ==
2719 got->Algorithm.Parameters.cbData,
2720 "Expected parameters of %d bytes, got %d\n",
2721 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2722 if (expected->Algorithm.Parameters.cbData)
2723 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2724 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2725 "Unexpected algorithm parameters\n");
2726 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2727 "Expected public key of %d bytes, got %d\n",
2728 expected->PublicKey.cbData, got->PublicKey.cbData);
2729 if (expected->PublicKey.cbData)
2730 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2731 got->PublicKey.cbData), "Unexpected public key value\n");
2734 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2736 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2737 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2738 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2739 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2740 DWORD i;
2741 BOOL ret;
2742 BYTE *buf = NULL;
2743 DWORD bufSize = 0;
2745 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2747 /* The NULL form decodes to the decoded member */
2748 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2749 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2750 NULL, &buf, &bufSize);
2751 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2752 if (buf)
2754 comparePublicKeyInfo(&pubKeys[i].decoded,
2755 (CERT_PUBLIC_KEY_INFO *)buf);
2756 LocalFree(buf);
2758 /* The non-NULL form decodes to the original */
2759 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2760 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2761 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2762 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2763 if (buf)
2765 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2766 LocalFree(buf);
2769 /* Test with bogus (not valid DER) parameters */
2770 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2771 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2772 NULL, &buf, &bufSize);
2773 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2774 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2775 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2776 GetLastError());
2779 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2780 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2781 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2782 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2783 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2784 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2785 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2786 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2787 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2788 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2789 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2790 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2791 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2792 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2793 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2794 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2795 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2796 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2797 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2798 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2799 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2800 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2801 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2802 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2803 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2804 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2805 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2806 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2807 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2808 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2809 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2810 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2811 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2812 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2813 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2814 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2815 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2816 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2817 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2818 static const BYTE v1CertWithPubKey[] = {
2819 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2820 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2821 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2822 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2823 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2824 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2825 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2826 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2827 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2828 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2829 0x01,0x01 };
2830 static const BYTE v1CertWithPubKeyNoNull[] = {
2831 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2832 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2833 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2834 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2835 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2836 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2837 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2838 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2839 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2840 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2841 static const BYTE v1CertWithSubjectKeyId[] = {
2842 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2843 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2844 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2845 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2846 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2847 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2848 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2849 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2850 0x4c,0x61,0x6e,0x67,0x00 };
2852 static const BYTE serialNum[] = { 0x01 };
2854 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2856 BOOL ret;
2857 BYTE *buf = NULL;
2858 DWORD size = 0;
2859 CERT_INFO info = { 0 };
2860 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2861 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2862 CERT_EXTENSION ext;
2864 if (0)
2866 /* Test with NULL pvStructInfo (crashes on win9x) */
2867 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2868 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2869 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2870 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2872 /* Test with a V1 cert */
2873 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2874 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2875 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2876 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2877 if (buf)
2879 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2880 v1Cert[1] + 2, size);
2881 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2882 LocalFree(buf);
2884 /* Test v2 cert */
2885 info.dwVersion = CERT_V2;
2886 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2887 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2888 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2889 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2890 if (buf)
2892 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2893 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2894 LocalFree(buf);
2896 /* Test v3 cert */
2897 info.dwVersion = CERT_V3;
2898 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2899 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2900 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2901 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2902 if (buf)
2904 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2905 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2906 LocalFree(buf);
2908 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2909 * API doesn't prevent it)
2911 info.dwVersion = CERT_V1;
2912 info.cExtension = 1;
2913 info.rgExtension = &criticalExt;
2914 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2915 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2916 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2917 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2918 if (buf)
2920 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2921 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2922 LocalFree(buf);
2924 /* test v1 cert with a serial number */
2925 info.SerialNumber.cbData = sizeof(serialNum);
2926 info.SerialNumber.pbData = (BYTE *)serialNum;
2927 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2928 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2929 if (buf)
2931 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2932 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2933 LocalFree(buf);
2935 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2936 info.Issuer.cbData = sizeof(encodedCommonName);
2937 info.Issuer.pbData = (BYTE *)encodedCommonName;
2938 info.Subject.cbData = sizeof(encodedCommonName);
2939 info.Subject.pbData = (BYTE *)encodedCommonName;
2940 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2941 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2942 if (buf)
2944 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2945 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2946 LocalFree(buf);
2948 /* Add a public key */
2949 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2950 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2951 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2952 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2953 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2954 if (buf)
2956 ok(size == sizeof(v1CertWithPubKey) ||
2957 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2958 if (size == sizeof(v1CertWithPubKey))
2959 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2960 else if (size == sizeof(v1CertWithPubKeyNoNull))
2961 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2962 "Got unexpected value\n");
2963 LocalFree(buf);
2965 /* Remove the public key, and add a subject key identifier extension */
2966 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2967 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2968 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2969 ext.pszObjId = oid_subject_key_identifier;
2970 ext.fCritical = FALSE;
2971 ext.Value.cbData = sizeof(octetCommonNameValue);
2972 ext.Value.pbData = octetCommonNameValue;
2973 info.cExtension = 1;
2974 info.rgExtension = &ext;
2975 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2976 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2977 if (buf)
2979 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2980 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2981 LocalFree(buf);
2985 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2987 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2988 v1CertWithConstraints, v1CertWithSerial };
2989 BOOL ret;
2990 BYTE *buf = NULL;
2991 DWORD size = 0, i;
2993 /* Test with NULL pbEncoded */
2994 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2995 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2996 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2997 GetLastError() == OSS_BAD_ARG /* Win9x */),
2998 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2999 if (0)
3001 /* Crashes on win9x */
3002 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3003 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3004 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3005 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3007 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3008 * minimum a cert must have a non-zero serial number, an issuer, and a
3009 * subject.
3011 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3013 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3014 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3015 &buf, &size);
3016 ok(!ret, "Expected failure\n");
3018 /* Now check with serial number, subject and issuer specified */
3019 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3020 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3021 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3022 if (buf)
3024 CERT_INFO *info = (CERT_INFO *)buf;
3026 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3027 ok(info->SerialNumber.cbData == 1,
3028 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3029 ok(*info->SerialNumber.pbData == *serialNum,
3030 "Expected serial number %d, got %d\n", *serialNum,
3031 *info->SerialNumber.pbData);
3032 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3033 "Wrong size %d\n", info->Issuer.cbData);
3034 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3035 "Unexpected issuer\n");
3036 ok(info->Subject.cbData == sizeof(encodedCommonName),
3037 "Wrong size %d\n", info->Subject.cbData);
3038 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3039 info->Subject.cbData), "Unexpected subject\n");
3040 LocalFree(buf);
3042 /* Check again with pub key specified */
3043 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3044 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3045 &buf, &size);
3046 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3047 if (buf)
3049 CERT_INFO *info = (CERT_INFO *)buf;
3051 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3052 ok(info->SerialNumber.cbData == 1,
3053 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3054 ok(*info->SerialNumber.pbData == *serialNum,
3055 "Expected serial number %d, got %d\n", *serialNum,
3056 *info->SerialNumber.pbData);
3057 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3058 "Wrong size %d\n", info->Issuer.cbData);
3059 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3060 "Unexpected issuer\n");
3061 ok(info->Subject.cbData == sizeof(encodedCommonName),
3062 "Wrong size %d\n", info->Subject.cbData);
3063 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3064 info->Subject.cbData), "Unexpected subject\n");
3065 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3066 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3067 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3068 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3069 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3070 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3071 sizeof(aKey)), "Unexpected public key\n");
3072 LocalFree(buf);
3076 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3077 0xe, 0xf };
3079 static const BYTE signedBigCert[] = {
3080 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3081 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3082 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3083 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3084 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3085 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3086 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3087 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3088 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3089 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3090 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3091 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3093 static void test_encodeCert(DWORD dwEncoding)
3095 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3096 * also that bigCert is a NULL-terminated string, so don't count its
3097 * last byte (otherwise the signed cert won't decode.)
3099 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3100 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3101 BOOL ret;
3102 BYTE *buf = NULL;
3103 DWORD bufSize = 0;
3105 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3106 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3107 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3108 if (buf)
3110 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3111 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3112 LocalFree(buf);
3116 static void test_decodeCert(DWORD dwEncoding)
3118 BOOL ret;
3119 BYTE *buf = NULL;
3120 DWORD size = 0;
3122 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3123 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3124 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3125 if (buf)
3127 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3129 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3130 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3131 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3132 "Unexpected cert\n");
3133 ok(info->Signature.cbData == sizeof(hash),
3134 "Wrong signature size %d\n", info->Signature.cbData);
3135 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3136 "Unexpected signature\n");
3137 LocalFree(buf);
3139 /* A signed cert decodes as a CERT_INFO too */
3140 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3141 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3142 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3143 if (buf)
3145 CERT_INFO *info = (CERT_INFO *)buf;
3147 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3148 ok(info->SerialNumber.cbData == 1,
3149 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3150 ok(*info->SerialNumber.pbData == *serialNum,
3151 "Expected serial number %d, got %d\n", *serialNum,
3152 *info->SerialNumber.pbData);
3153 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3154 "Wrong size %d\n", info->Issuer.cbData);
3155 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3156 "Unexpected issuer\n");
3157 ok(info->Subject.cbData == sizeof(encodedCommonName),
3158 "Wrong size %d\n", info->Subject.cbData);
3159 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3160 info->Subject.cbData), "Unexpected subject\n");
3161 LocalFree(buf);
3165 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3166 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3167 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3168 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3169 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3170 0x00, 0x03 };
3171 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3172 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3173 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3174 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3175 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3176 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3177 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3178 0x2e, 0x6f, 0x72, 0x67 };
3179 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3180 CRL_REASON_AFFILIATION_CHANGED;
3182 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3184 CRL_DIST_POINTS_INFO info = { 0 };
3185 CRL_DIST_POINT point = { { 0 } };
3186 CERT_ALT_NAME_ENTRY entry = { 0 };
3187 BOOL ret;
3188 BYTE *buf = NULL;
3189 DWORD size = 0;
3191 /* Test with an empty info */
3192 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3193 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3194 ok(!ret && GetLastError() == E_INVALIDARG,
3195 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3196 /* Test with one empty dist point */
3197 info.cDistPoint = 1;
3198 info.rgDistPoint = &point;
3199 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3200 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3201 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3202 if (buf)
3204 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3205 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3206 LocalFree(buf);
3208 /* A dist point with an invalid name */
3209 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3210 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3211 U(entry).pwszURL = (LPWSTR)nihongoURL;
3212 U(point.DistPointName).FullName.cAltEntry = 1;
3213 U(point.DistPointName).FullName.rgAltEntry = &entry;
3214 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3215 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3216 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3217 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3218 /* The first invalid character is at index 7 */
3219 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3220 "Expected invalid char at index 7, got %d\n",
3221 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3222 /* A dist point with (just) a valid name */
3223 U(entry).pwszURL = (LPWSTR)url;
3224 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3225 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3226 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3227 if (buf)
3229 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3230 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3231 LocalFree(buf);
3233 /* A dist point with (just) reason flags */
3234 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3235 point.ReasonFlags.cbData = sizeof(crlReason);
3236 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3237 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3238 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3239 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3240 if (buf)
3242 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3243 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3244 LocalFree(buf);
3246 /* A dist point with just an issuer */
3247 point.ReasonFlags.cbData = 0;
3248 point.CRLIssuer.cAltEntry = 1;
3249 point.CRLIssuer.rgAltEntry = &entry;
3250 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3251 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3252 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3253 if (buf)
3255 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3256 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3257 LocalFree(buf);
3259 /* A dist point with both a name and an issuer */
3260 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3261 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3262 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3263 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3264 if (buf)
3266 ok(size == sizeof(distPointWithUrlAndIssuer),
3267 "Wrong size %d\n", size);
3268 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3269 LocalFree(buf);
3273 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3275 BOOL ret;
3276 BYTE *buf = NULL;
3277 DWORD size = 0;
3278 PCRL_DIST_POINTS_INFO info;
3279 PCRL_DIST_POINT point;
3280 PCERT_ALT_NAME_ENTRY entry;
3282 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3283 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3284 &buf, &size);
3285 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3286 if (ret)
3288 info = (PCRL_DIST_POINTS_INFO)buf;
3289 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3290 "Wrong size %d\n", size);
3291 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3292 info->cDistPoint);
3293 point = info->rgDistPoint;
3294 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3295 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3296 point->DistPointName.dwDistPointNameChoice);
3297 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3298 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3299 LocalFree(buf);
3301 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3302 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3303 &buf, &size);
3304 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3305 if (ret)
3307 info = (PCRL_DIST_POINTS_INFO)buf;
3308 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3309 "Wrong size %d\n", size);
3310 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3311 info->cDistPoint);
3312 point = info->rgDistPoint;
3313 ok(point->DistPointName.dwDistPointNameChoice ==
3314 CRL_DIST_POINT_FULL_NAME,
3315 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3316 point->DistPointName.dwDistPointNameChoice);
3317 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3318 "Expected 1 name entry, got %d\n",
3319 U(point->DistPointName).FullName.cAltEntry);
3320 entry = U(point->DistPointName).FullName.rgAltEntry;
3321 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3322 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3323 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3324 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3325 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3326 LocalFree(buf);
3328 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3329 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3330 NULL, &buf, &size);
3331 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3332 if (ret)
3334 info = (PCRL_DIST_POINTS_INFO)buf;
3335 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3336 "Wrong size %d\n", size);
3337 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3338 info->cDistPoint);
3339 point = info->rgDistPoint;
3340 ok(point->DistPointName.dwDistPointNameChoice ==
3341 CRL_DIST_POINT_NO_NAME,
3342 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3343 point->DistPointName.dwDistPointNameChoice);
3344 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3345 "Expected reason length\n");
3346 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3347 "Unexpected reason\n");
3348 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3349 LocalFree(buf);
3351 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3352 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3353 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3354 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3355 if (ret)
3357 info = (PCRL_DIST_POINTS_INFO)buf;
3358 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3359 "Wrong size %d\n", size);
3360 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3361 info->cDistPoint);
3362 point = info->rgDistPoint;
3363 ok(point->DistPointName.dwDistPointNameChoice ==
3364 CRL_DIST_POINT_FULL_NAME,
3365 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3366 point->DistPointName.dwDistPointNameChoice);
3367 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3368 "Expected 1 name entry, got %d\n",
3369 U(point->DistPointName).FullName.cAltEntry);
3370 entry = U(point->DistPointName).FullName.rgAltEntry;
3371 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3372 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3373 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3374 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3375 ok(point->CRLIssuer.cAltEntry == 1,
3376 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3377 entry = point->CRLIssuer.rgAltEntry;
3378 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3379 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3380 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3381 LocalFree(buf);
3385 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3386 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3387 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3388 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3389 0x67 };
3391 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3393 BOOL ret;
3394 BYTE *buf = NULL;
3395 DWORD size = 0;
3396 CRL_ISSUING_DIST_POINT point = { { 0 } };
3397 CERT_ALT_NAME_ENTRY entry;
3399 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3400 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3401 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3403 skip("no X509_ISSUING_DIST_POINT encode support\n");
3404 return;
3406 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3407 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3408 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3409 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3410 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3411 if (buf)
3413 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3414 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3415 LocalFree(buf);
3417 /* nonsensical flags */
3418 point.fOnlyContainsUserCerts = TRUE;
3419 point.fOnlyContainsCACerts = TRUE;
3420 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3421 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3422 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3423 if (buf)
3425 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3426 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3427 LocalFree(buf);
3429 /* unimplemented name type */
3430 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3431 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3432 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3433 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3434 ok(!ret && GetLastError() == E_INVALIDARG,
3435 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3436 /* empty name */
3437 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3438 U(point.DistPointName).FullName.cAltEntry = 0;
3439 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3440 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3441 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3442 if (buf)
3444 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3445 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3446 LocalFree(buf);
3448 /* name with URL entry */
3449 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3450 U(entry).pwszURL = (LPWSTR)url;
3451 U(point.DistPointName).FullName.cAltEntry = 1;
3452 U(point.DistPointName).FullName.rgAltEntry = &entry;
3453 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3454 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3455 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3456 if (buf)
3458 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3459 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3460 LocalFree(buf);
3464 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3465 const CERT_ALT_NAME_ENTRY *got)
3467 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3468 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3469 got->dwAltNameChoice);
3470 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3472 switch (got->dwAltNameChoice)
3474 case CERT_ALT_NAME_RFC822_NAME:
3475 case CERT_ALT_NAME_DNS_NAME:
3476 case CERT_ALT_NAME_EDI_PARTY_NAME:
3477 case CERT_ALT_NAME_URL:
3478 case CERT_ALT_NAME_REGISTERED_ID:
3479 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3480 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3481 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3482 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3483 "Unexpected name\n");
3484 break;
3485 case CERT_ALT_NAME_X400_ADDRESS:
3486 case CERT_ALT_NAME_DIRECTORY_NAME:
3487 case CERT_ALT_NAME_IP_ADDRESS:
3488 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3489 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3490 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3491 U(*got).IPAddress.cbData), "Unexpected value\n");
3492 break;
3497 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3498 const CERT_ALT_NAME_INFO *got)
3500 DWORD i;
3502 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3503 expected->cAltEntry, got->cAltEntry);
3504 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3505 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3508 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3509 const CRL_DIST_POINT_NAME *got)
3511 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3512 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3513 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3514 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3517 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3518 const CRL_ISSUING_DIST_POINT *got)
3520 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3521 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3522 "Unexpected fOnlyContainsUserCerts\n");
3523 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3524 "Unexpected fOnlyContainsCACerts\n");
3525 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3526 "Unexpected reason flags\n");
3527 ok(got->fIndirectCRL == expected->fIndirectCRL,
3528 "Unexpected fIndirectCRL\n");
3531 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3533 BOOL ret;
3534 BYTE *buf = NULL;
3535 DWORD size = 0;
3536 CRL_ISSUING_DIST_POINT point = { { 0 } };
3538 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3539 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3540 &buf, &size);
3541 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3543 skip("no X509_ISSUING_DIST_POINT decode support\n");
3544 return;
3546 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3547 if (ret)
3549 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3550 LocalFree(buf);
3552 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3553 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3554 &buf, &size);
3555 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3556 if (ret)
3558 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3559 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3560 LocalFree(buf);
3562 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3563 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3564 &buf, &size);
3565 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3566 if (ret)
3568 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3569 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3570 U(point.DistPointName).FullName.cAltEntry = 0;
3571 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3572 LocalFree(buf);
3574 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3575 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3576 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3577 if (ret)
3579 CERT_ALT_NAME_ENTRY entry;
3581 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3582 U(entry).pwszURL = (LPWSTR)url;
3583 U(point.DistPointName).FullName.cAltEntry = 1;
3584 U(point.DistPointName).FullName.rgAltEntry = &entry;
3585 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3586 LocalFree(buf);
3590 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3591 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3592 0x30, 0x5a };
3593 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3594 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3595 0x30, 0x30, 0x30, 0x30, 0x5a };
3596 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3597 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3598 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3599 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3600 0x5a };
3601 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3602 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3603 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3604 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3605 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3606 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3607 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3608 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3609 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3610 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3611 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3612 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3613 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3614 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3615 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3616 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3617 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3618 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3619 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3620 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3621 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3622 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3623 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3624 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3625 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3626 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3627 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3628 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3629 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3630 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3631 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3632 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3633 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3634 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3635 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3636 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3637 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3638 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3639 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3640 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3642 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3644 BOOL ret;
3645 BYTE *buf = NULL;
3646 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3647 DWORD size = 0;
3648 CRL_INFO info = { 0 };
3649 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3650 CERT_EXTENSION ext;
3652 /* Test with a V1 CRL */
3653 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3654 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3656 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3657 if (buf)
3659 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3660 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3661 LocalFree(buf);
3663 /* Test v2 CRL */
3664 info.dwVersion = CRL_V2;
3665 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3666 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3667 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3668 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3669 if (buf)
3671 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3672 v2CRL[1] + 2, size);
3673 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3674 LocalFree(buf);
3676 /* v1 CRL with a name */
3677 info.dwVersion = CRL_V1;
3678 info.Issuer.cbData = sizeof(encodedCommonName);
3679 info.Issuer.pbData = (BYTE *)encodedCommonName;
3680 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3681 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3682 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3683 if (buf)
3685 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3686 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3687 LocalFree(buf);
3689 if (0)
3691 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3692 info.cCRLEntry = 1;
3693 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3694 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3695 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3696 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3698 /* now set an empty entry */
3699 info.cCRLEntry = 1;
3700 info.rgCRLEntry = &entry;
3701 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3702 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3703 if (buf)
3705 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3706 "Wrong size %d\n", size);
3707 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3708 "Got unexpected value\n");
3709 LocalFree(buf);
3711 /* an entry with a serial number */
3712 entry.SerialNumber.cbData = sizeof(serialNum);
3713 entry.SerialNumber.pbData = (BYTE *)serialNum;
3714 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3715 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3716 if (buf)
3718 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3719 "Wrong size %d\n", size);
3720 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3721 "Got unexpected value\n");
3722 LocalFree(buf);
3724 /* an entry with an extension */
3725 entry.cExtension = 1;
3726 entry.rgExtension = &criticalExt;
3727 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3728 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3729 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3730 if (buf)
3732 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3733 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3734 LocalFree(buf);
3736 /* a CRL with an extension */
3737 entry.cExtension = 0;
3738 info.cExtension = 1;
3739 info.rgExtension = &criticalExt;
3740 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3741 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3742 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3743 if (buf)
3745 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3746 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3747 LocalFree(buf);
3749 /* a v2 CRL with an extension, this time non-critical */
3750 info.dwVersion = CRL_V2;
3751 info.rgExtension = &nonCriticalExt;
3752 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3753 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3754 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3755 if (buf)
3757 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3758 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3759 LocalFree(buf);
3761 /* a v2 CRL with an issuing dist point extension */
3762 ext.pszObjId = oid_issuing_dist_point;
3763 ext.fCritical = TRUE;
3764 ext.Value.cbData = sizeof(urlIDP);
3765 ext.Value.pbData = (LPBYTE)urlIDP;
3766 entry.rgExtension = &ext;
3767 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3768 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3769 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3770 if (buf)
3772 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3773 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3774 LocalFree(buf);
3778 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3779 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3780 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3781 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3782 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3783 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3784 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3785 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3786 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3787 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3788 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3789 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3790 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3791 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3792 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3793 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3794 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3795 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3796 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3797 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3798 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3799 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3800 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3801 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3802 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3803 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3804 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3805 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3806 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3807 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3808 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3809 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3810 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3811 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3812 0xcd };
3813 static const BYTE verisignCRLWithLotsOfEntries[] = {
3814 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3815 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3816 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3817 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3818 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3819 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3820 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3821 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3822 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3823 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3824 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3825 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3826 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3827 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3828 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3829 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3830 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3831 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3832 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3833 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3834 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3835 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3836 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3837 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3838 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3839 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3840 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3841 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3842 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3843 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3844 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3845 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3846 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3847 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3848 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3849 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3850 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3851 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3852 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3853 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3854 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3855 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3856 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3857 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3858 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3859 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3860 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3861 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3862 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3863 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3864 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3865 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3866 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3867 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3868 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3869 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3870 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3871 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3872 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3873 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3874 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3875 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3876 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3877 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3878 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3879 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3880 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3881 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3882 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3883 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3884 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3885 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3886 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3887 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3888 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3889 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3890 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3891 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3892 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3893 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3894 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3895 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3896 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3897 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3898 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3899 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3900 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3901 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3902 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3903 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3904 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3905 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3906 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3907 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3908 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3909 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3910 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3911 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3912 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3913 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3914 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3915 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3916 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3917 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3918 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3919 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3920 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3921 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3922 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3923 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3924 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3925 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3926 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3927 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3928 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3929 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3930 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3931 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3932 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3933 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3934 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3935 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3936 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3937 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3938 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3939 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3940 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3941 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3942 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3943 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3944 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3945 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3946 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3947 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3948 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3949 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3950 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3951 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3952 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3953 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3954 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3955 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3956 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3957 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3958 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3959 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3960 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3961 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3962 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3963 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3964 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3965 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3966 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3967 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3968 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3969 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3970 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3971 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3972 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3973 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3974 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3975 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3976 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3977 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3978 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3979 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3980 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3981 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3982 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3983 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3984 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3985 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3986 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3987 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3988 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3989 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3990 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3991 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3992 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3993 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3994 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3995 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3996 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3997 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3998 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3999 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4000 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4001 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4002 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4003 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4004 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4005 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4006 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4007 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4008 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4009 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4010 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4011 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4012 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4013 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4014 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4015 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4016 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4017 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4018 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4019 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4020 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4021 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4022 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4023 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4024 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4025 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4026 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4027 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4028 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4029 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4030 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4031 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4032 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4033 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4034 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4035 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4036 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4037 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4038 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4039 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4040 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4041 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4042 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4043 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4044 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4045 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4046 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4047 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4048 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4049 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4050 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4051 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4052 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4053 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4054 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4055 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4056 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4057 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4058 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4059 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4060 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4061 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4062 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4063 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4064 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4065 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4066 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4067 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4068 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4069 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4070 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4071 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4072 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4073 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4074 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4075 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4076 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4077 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4078 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4079 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4080 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4081 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4082 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4083 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4084 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4085 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4086 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4087 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4088 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4089 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4090 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4091 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4092 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4093 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4094 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4095 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4096 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4097 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4098 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4099 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4100 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4101 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4102 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4103 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4104 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4105 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4106 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4107 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4108 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4109 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4110 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4111 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4112 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4113 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4114 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4115 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4116 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4117 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4118 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4119 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4120 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4121 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4122 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4123 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4124 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4125 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4126 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4127 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4128 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4129 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4130 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4131 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4132 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4133 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4134 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4135 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4136 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4137 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4138 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4139 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4140 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4141 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4142 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4143 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4144 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4145 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4146 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4147 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4148 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4149 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4150 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4151 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4152 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4153 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4154 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4155 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4156 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4157 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4158 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4159 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4160 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4161 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4162 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4163 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4164 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4165 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4166 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4167 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4168 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4169 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4170 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4171 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4172 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4173 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4174 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4175 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4176 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4177 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4178 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4179 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4180 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4181 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4182 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4183 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4184 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4185 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4186 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4187 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4188 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4189 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4190 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4191 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4192 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4193 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4194 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4195 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4196 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4197 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4198 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4199 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4200 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4201 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4202 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4203 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4204 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4205 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4206 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4207 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4208 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4209 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4210 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4211 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4212 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4213 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4214 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4215 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4216 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4217 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4218 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4219 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4220 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4221 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4222 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4223 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4224 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4225 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4226 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4227 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4228 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4229 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4230 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4231 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4232 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4233 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4234 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4235 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4236 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4237 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4238 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4239 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4240 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4241 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4242 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4243 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4244 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4245 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4246 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4247 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4248 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4249 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4250 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4251 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4252 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4253 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4254 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4255 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4256 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4257 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4258 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4259 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4260 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4261 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4262 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4263 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4264 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4265 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4266 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4267 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4268 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4269 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4270 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4271 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4272 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4273 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4274 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4275 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4276 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4277 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4278 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4279 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4280 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4281 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4282 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4283 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4284 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4285 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4286 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4287 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4288 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4289 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4290 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4291 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4292 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4293 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4294 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4295 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4296 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4297 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4298 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4299 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4300 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4301 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4302 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4303 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4304 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4305 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4306 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4307 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4308 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4309 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4310 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4311 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4312 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4313 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4314 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4315 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4316 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4317 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4318 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4319 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4320 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4321 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4323 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4325 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4326 BOOL ret;
4327 BYTE *buf = NULL;
4328 DWORD size = 0, i;
4330 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4332 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4333 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4334 &buf, &size);
4335 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4336 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4337 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4338 GetLastError());
4340 /* at a minimum, a CRL must contain an issuer: */
4341 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4342 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4343 &buf, &size);
4344 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4345 if (buf)
4347 CRL_INFO *info = (CRL_INFO *)buf;
4349 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4350 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4351 info->cCRLEntry);
4352 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4353 "Wrong issuer size %d\n", info->Issuer.cbData);
4354 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4355 "Unexpected issuer\n");
4356 LocalFree(buf);
4358 /* check decoding with an empty CRL entry */
4359 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4360 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4361 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4362 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4363 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4364 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4365 GetLastError());
4366 /* with a real CRL entry */
4367 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4368 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4369 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4370 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4371 if (buf)
4373 CRL_INFO *info = (CRL_INFO *)buf;
4374 CRL_ENTRY *entry;
4376 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4377 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4378 info->cCRLEntry);
4379 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4380 entry = info->rgCRLEntry;
4381 ok(entry->SerialNumber.cbData == 1,
4382 "Expected serial number size 1, got %d\n",
4383 entry->SerialNumber.cbData);
4384 ok(*entry->SerialNumber.pbData == *serialNum,
4385 "Expected serial number %d, got %d\n", *serialNum,
4386 *entry->SerialNumber.pbData);
4387 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4388 "Wrong issuer size %d\n", info->Issuer.cbData);
4389 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4390 "Unexpected issuer\n");
4391 LocalFree(buf);
4393 /* a real CRL from verisign that has extensions */
4394 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4395 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4396 NULL, &buf, &size);
4397 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4398 if (buf)
4400 CRL_INFO *info = (CRL_INFO *)buf;
4401 CRL_ENTRY *entry;
4403 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4404 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4405 info->cCRLEntry);
4406 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4407 entry = info->rgCRLEntry;
4408 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4409 info->cExtension);
4410 LocalFree(buf);
4412 /* another real CRL from verisign that has lots of entries */
4413 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4414 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4415 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4416 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4417 if (buf)
4419 CRL_INFO *info = (CRL_INFO *)buf;
4421 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4422 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4423 info->cCRLEntry);
4424 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4425 info->cExtension);
4426 LocalFree(buf);
4428 /* and finally, with an extension */
4429 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4430 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4431 NULL, &buf, &size);
4432 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4433 if (buf)
4435 CRL_INFO *info = (CRL_INFO *)buf;
4436 CRL_ENTRY *entry;
4438 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4439 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4440 info->cCRLEntry);
4441 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4442 entry = info->rgCRLEntry;
4443 ok(entry->SerialNumber.cbData == 1,
4444 "Expected serial number size 1, got %d\n",
4445 entry->SerialNumber.cbData);
4446 ok(*entry->SerialNumber.pbData == *serialNum,
4447 "Expected serial number %d, got %d\n", *serialNum,
4448 *entry->SerialNumber.pbData);
4449 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4450 "Wrong issuer size %d\n", info->Issuer.cbData);
4451 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4452 "Unexpected issuer\n");
4453 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4454 info->cExtension);
4455 LocalFree(buf);
4457 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4458 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4459 NULL, &buf, &size);
4460 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4461 if (buf)
4463 CRL_INFO *info = (CRL_INFO *)buf;
4465 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4466 info->cExtension);
4467 LocalFree(buf);
4469 /* And again, with an issuing dist point */
4470 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4471 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4472 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4473 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4474 if (buf)
4476 CRL_INFO *info = (CRL_INFO *)buf;
4478 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4479 info->cExtension);
4480 LocalFree(buf);
4484 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4485 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4486 static const BYTE encodedUsage[] = {
4487 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4488 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4489 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4491 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4493 BOOL ret;
4494 BYTE *buf = NULL;
4495 DWORD size = 0;
4496 CERT_ENHKEY_USAGE usage;
4498 /* Test with empty usage */
4499 usage.cUsageIdentifier = 0;
4500 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4501 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4502 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4503 if (buf)
4505 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4506 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4507 LocalFree(buf);
4509 /* Test with a few usages */
4510 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4511 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4512 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4513 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4514 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4515 if (buf)
4517 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4518 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4519 LocalFree(buf);
4523 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4525 BOOL ret;
4526 LPBYTE buf = NULL;
4527 DWORD size = 0;
4529 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4530 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4531 &buf, &size);
4532 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4533 if (buf)
4535 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4537 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4538 "Wrong size %d\n", size);
4539 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4540 usage->cUsageIdentifier);
4541 LocalFree(buf);
4543 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4544 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4545 &buf, &size);
4546 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4547 if (buf)
4549 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4550 DWORD i;
4552 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4553 "Wrong size %d\n", size);
4554 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4555 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4556 for (i = 0; i < usage->cUsageIdentifier; i++)
4557 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4558 "Expected OID %s, got %s\n", keyUsages[i],
4559 usage->rgpszUsageIdentifier[i]);
4560 LocalFree(buf);
4564 static BYTE keyId[] = { 1,2,3,4 };
4565 static const BYTE authorityKeyIdWithId[] = {
4566 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4567 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4568 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4569 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4570 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4572 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4574 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4575 BOOL ret;
4576 BYTE *buf = NULL;
4577 DWORD size = 0;
4579 /* Test with empty id */
4580 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4581 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4582 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4583 if (buf)
4585 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4586 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4587 LocalFree(buf);
4589 /* With just a key id */
4590 info.KeyId.cbData = sizeof(keyId);
4591 info.KeyId.pbData = keyId;
4592 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4593 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4594 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4595 if (buf)
4597 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4598 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4599 LocalFree(buf);
4601 /* With just an issuer */
4602 info.KeyId.cbData = 0;
4603 info.CertIssuer.cbData = sizeof(encodedCommonName);
4604 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4605 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4606 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4607 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4608 if (buf)
4610 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4611 size);
4612 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4613 LocalFree(buf);
4615 /* With just a serial number */
4616 info.CertIssuer.cbData = 0;
4617 info.CertSerialNumber.cbData = sizeof(serialNum);
4618 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4619 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4620 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4621 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4622 if (buf)
4624 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4625 size);
4626 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4627 LocalFree(buf);
4631 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4633 BOOL ret;
4634 LPBYTE buf = NULL;
4635 DWORD size = 0;
4637 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4638 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4639 &buf, &size);
4640 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4641 if (buf)
4643 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4645 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4646 size);
4647 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4648 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4649 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4650 LocalFree(buf);
4652 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4653 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4654 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4655 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4656 if (buf)
4658 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4660 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4661 size);
4662 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4663 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4664 "Unexpected key id\n");
4665 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4666 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4667 LocalFree(buf);
4669 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4670 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4671 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4672 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4673 if (buf)
4675 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4677 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4678 size);
4679 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4680 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4681 "Unexpected issuer len\n");
4682 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4683 sizeof(encodedCommonName)), "Unexpected issuer\n");
4684 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4685 LocalFree(buf);
4687 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4688 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4689 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4690 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4691 if (buf)
4693 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4695 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4696 size);
4697 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4698 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4699 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4700 "Unexpected serial number len\n");
4701 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4702 "Unexpected serial number\n");
4703 LocalFree(buf);
4707 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4708 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4709 0x6f,0x72,0x67 };
4711 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4713 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4714 CERT_ALT_NAME_ENTRY entry = { 0 };
4715 BOOL ret;
4716 BYTE *buf = NULL;
4717 DWORD size = 0;
4719 /* Test with empty id */
4720 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4721 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4722 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4723 if (buf)
4725 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4726 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4727 LocalFree(buf);
4729 /* With just a key id */
4730 info.KeyId.cbData = sizeof(keyId);
4731 info.KeyId.pbData = keyId;
4732 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4733 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4734 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4735 if (buf)
4737 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4738 size);
4739 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4740 LocalFree(buf);
4742 /* With a bogus issuer name */
4743 info.KeyId.cbData = 0;
4744 info.AuthorityCertIssuer.cAltEntry = 1;
4745 info.AuthorityCertIssuer.rgAltEntry = &entry;
4746 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4747 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4748 ok(!ret && GetLastError() == E_INVALIDARG,
4749 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4750 /* With an issuer name */
4751 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4752 U(entry).pwszURL = (LPWSTR)url;
4753 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4754 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4755 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4756 if (buf)
4758 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4759 size);
4760 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4761 "Unexpected value\n");
4762 LocalFree(buf);
4764 /* With just a serial number */
4765 info.AuthorityCertIssuer.cAltEntry = 0;
4766 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4767 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4768 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4769 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4770 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4771 if (buf)
4773 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4774 size);
4775 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4776 LocalFree(buf);
4780 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4782 BOOL ret;
4783 LPBYTE buf = NULL;
4784 DWORD size = 0;
4786 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4787 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4788 &buf, &size);
4789 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4790 if (buf)
4792 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4794 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4795 size);
4796 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4797 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4798 "Expected no issuer name entries\n");
4799 ok(info->AuthorityCertSerialNumber.cbData == 0,
4800 "Expected no serial number\n");
4801 LocalFree(buf);
4803 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4804 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4805 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4806 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4807 if (buf)
4809 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4811 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4812 size);
4813 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4814 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4815 "Unexpected key id\n");
4816 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4817 "Expected no issuer name entries\n");
4818 ok(info->AuthorityCertSerialNumber.cbData == 0,
4819 "Expected no serial number\n");
4820 LocalFree(buf);
4822 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4823 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4824 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4825 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4826 if (buf)
4828 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4830 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4831 size);
4832 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4833 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4834 "Expected 1 issuer entry, got %d\n",
4835 info->AuthorityCertIssuer.cAltEntry);
4836 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4837 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4838 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4839 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4840 url), "Unexpected URL\n");
4841 ok(info->AuthorityCertSerialNumber.cbData == 0,
4842 "Expected no serial number\n");
4843 LocalFree(buf);
4845 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4846 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4847 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4848 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4849 if (buf)
4851 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4853 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4854 size);
4855 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4856 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4857 "Expected no issuer name entries\n");
4858 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4859 "Unexpected serial number len\n");
4860 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4861 sizeof(serialNum)), "Unexpected serial number\n");
4862 LocalFree(buf);
4866 static const BYTE authorityInfoAccessWithUrl[] = {
4867 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4868 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4869 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4870 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4871 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4872 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4874 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4876 static char oid1[] = "1.2.3";
4877 static char oid2[] = "1.5.6";
4878 BOOL ret;
4879 BYTE *buf = NULL;
4880 DWORD size = 0;
4881 CERT_ACCESS_DESCRIPTION accessDescription[2];
4882 CERT_AUTHORITY_INFO_ACCESS aia;
4884 memset(accessDescription, 0, sizeof(accessDescription));
4885 aia.cAccDescr = 0;
4886 aia.rgAccDescr = NULL;
4887 /* Having no access descriptions is allowed */
4888 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4889 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4890 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4891 if (buf)
4893 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4894 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4895 LocalFree(buf);
4896 buf = NULL;
4898 /* It can't have an empty access method */
4899 aia.cAccDescr = 1;
4900 aia.rgAccDescr = accessDescription;
4901 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4902 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4903 ok(!ret && (GetLastError() == E_INVALIDARG ||
4904 GetLastError() == OSS_LIMITED /* Win9x */),
4905 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4906 /* It can't have an empty location */
4907 accessDescription[0].pszAccessMethod = oid1;
4908 SetLastError(0xdeadbeef);
4909 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4910 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4911 ok(!ret && GetLastError() == E_INVALIDARG,
4912 "expected E_INVALIDARG, got %08x\n", GetLastError());
4913 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4914 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4915 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4916 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4917 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4918 if (buf)
4920 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4921 size);
4922 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4923 "unexpected value\n");
4924 LocalFree(buf);
4925 buf = NULL;
4927 accessDescription[1].pszAccessMethod = oid2;
4928 accessDescription[1].AccessLocation.dwAltNameChoice =
4929 CERT_ALT_NAME_IP_ADDRESS;
4930 U(accessDescription[1].AccessLocation).IPAddress.cbData =
4931 sizeof(encodedIPAddr);
4932 U(accessDescription[1].AccessLocation).IPAddress.pbData =
4933 (LPBYTE)encodedIPAddr;
4934 aia.cAccDescr = 2;
4935 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4937 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4938 if (buf)
4940 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4941 "unexpected size %d\n", size);
4942 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4943 "unexpected value\n");
4944 LocalFree(buf);
4945 buf = NULL;
4949 static void compareAuthorityInfoAccess(LPCSTR header,
4950 const CERT_AUTHORITY_INFO_ACCESS *expected,
4951 const CERT_AUTHORITY_INFO_ACCESS *got)
4953 DWORD i;
4955 ok(expected->cAccDescr == got->cAccDescr,
4956 "%s: expected %d access descriptions, got %d\n", header,
4957 expected->cAccDescr, got->cAccDescr);
4958 for (i = 0; i < expected->cAccDescr; i++)
4960 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4961 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4962 header, i, expected->rgAccDescr[i].pszAccessMethod,
4963 got->rgAccDescr[i].pszAccessMethod);
4964 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4965 &got->rgAccDescr[i].AccessLocation);
4969 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4971 static char oid1[] = "1.2.3";
4972 static char oid2[] = "1.5.6";
4973 BOOL ret;
4974 LPBYTE buf = NULL;
4975 DWORD size = 0;
4977 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4978 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4979 &buf, &size);
4980 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4981 if (buf)
4983 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4985 compareAuthorityInfoAccess("empty AIA", &aia,
4986 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4987 LocalFree(buf);
4988 buf = NULL;
4990 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4991 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4992 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4993 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4994 if (buf)
4996 CERT_ACCESS_DESCRIPTION accessDescription;
4997 CERT_AUTHORITY_INFO_ACCESS aia;
4999 accessDescription.pszAccessMethod = oid1;
5000 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5001 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5002 aia.cAccDescr = 1;
5003 aia.rgAccDescr = &accessDescription;
5004 compareAuthorityInfoAccess("AIA with URL", &aia,
5005 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5006 LocalFree(buf);
5007 buf = NULL;
5009 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5010 authorityInfoAccessWithUrlAndIPAddr,
5011 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5012 NULL, &buf, &size);
5013 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5014 if (buf)
5016 CERT_ACCESS_DESCRIPTION accessDescription[2];
5017 CERT_AUTHORITY_INFO_ACCESS aia;
5019 accessDescription[0].pszAccessMethod = oid1;
5020 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5021 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5022 accessDescription[1].pszAccessMethod = oid2;
5023 accessDescription[1].AccessLocation.dwAltNameChoice =
5024 CERT_ALT_NAME_IP_ADDRESS;
5025 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5026 sizeof(encodedIPAddr);
5027 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5028 (LPBYTE)encodedIPAddr;
5029 aia.cAccDescr = 2;
5030 aia.rgAccDescr = accessDescription;
5031 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5032 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5033 LocalFree(buf);
5034 buf = NULL;
5038 static const BYTE emptyCTL[] = {
5039 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5040 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5041 static const BYTE emptyCTLWithVersion1[] = {
5042 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5043 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5044 static const BYTE ctlWithUsageIdentifier[] = {
5045 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5046 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5047 static const BYTE ctlWithListIdentifier[] = {
5048 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5049 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5050 static const BYTE ctlWithSequenceNumber[] = {
5051 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5052 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5053 static const BYTE ctlWithThisUpdate[] = {
5054 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5055 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5056 static const BYTE ctlWithThisAndNextUpdate[] = {
5057 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5058 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5059 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5060 static const BYTE ctlWithAlgId[] = {
5061 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5062 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5063 static const BYTE ctlWithBogusEntry[] = {
5064 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5065 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5066 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5067 static const BYTE ctlWithOneEntry[] = {
5068 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5069 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5070 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5071 static const BYTE ctlWithTwoEntries[] = {
5072 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5073 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5074 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5075 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5076 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5078 static void test_encodeCTL(DWORD dwEncoding)
5080 static char oid1[] = "1.2.3";
5081 static char oid2[] = "1.5.6";
5082 char *pOid1 = oid1;
5083 BOOL ret;
5084 BYTE *buf = NULL;
5085 DWORD size = 0;
5086 CTL_INFO info;
5087 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5088 CTL_ENTRY ctlEntry[2];
5089 CRYPT_ATTRIBUTE attr1, attr2;
5090 CRYPT_ATTR_BLOB value1, value2;
5092 memset(&info, 0, sizeof(info));
5093 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5094 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5095 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5096 if (buf)
5098 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5099 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5100 LocalFree(buf);
5101 buf = NULL;
5103 info.dwVersion = 1;
5104 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5105 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5106 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5107 if (buf)
5109 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5110 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5111 LocalFree(buf);
5112 buf = NULL;
5114 info.dwVersion = 0;
5115 info.SubjectUsage.cUsageIdentifier = 1;
5116 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5117 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5118 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5119 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5120 if (buf)
5122 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5123 size);
5124 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5125 LocalFree(buf);
5126 buf = NULL;
5128 info.SubjectUsage.cUsageIdentifier = 0;
5129 info.ListIdentifier.cbData = sizeof(serialNum);
5130 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5131 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5132 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5133 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5134 if (buf)
5136 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5137 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5138 LocalFree(buf);
5139 buf = NULL;
5141 info.ListIdentifier.cbData = 0;
5142 info.SequenceNumber.cbData = sizeof(serialNum);
5143 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5144 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5145 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5146 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5147 if (buf)
5149 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5150 size);
5151 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5152 LocalFree(buf);
5153 buf = NULL;
5155 info.SequenceNumber.cbData = 0;
5156 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5157 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5159 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5160 if (buf)
5162 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5163 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5164 LocalFree(buf);
5165 buf = NULL;
5167 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5168 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5169 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5170 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5171 if (buf)
5173 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5174 size);
5175 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5176 LocalFree(buf);
5177 buf = NULL;
5179 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5180 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5181 info.SubjectAlgorithm.pszObjId = oid2;
5182 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5183 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5184 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5185 if (buf)
5187 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5188 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5189 LocalFree(buf);
5190 buf = NULL;
5192 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5193 * (see tests below) but it'll encode fine.
5195 info.SubjectAlgorithm.pszObjId = NULL;
5196 value1.cbData = sizeof(serialNum);
5197 value1.pbData = (LPBYTE)serialNum;
5198 attr1.pszObjId = oid1;
5199 attr1.cValue = 1;
5200 attr1.rgValue = &value1;
5201 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5202 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5203 ctlEntry[0].cAttribute = 1;
5204 ctlEntry[0].rgAttribute = &attr1;
5205 info.cCTLEntry = 1;
5206 info.rgCTLEntry = ctlEntry;
5207 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5208 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5209 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5210 if (buf)
5212 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5213 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5214 LocalFree(buf);
5215 buf = NULL;
5217 value1.cbData = sizeof(emptySequence);
5218 value1.pbData = (LPBYTE)emptySequence;
5219 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5220 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5221 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5222 if (buf)
5224 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5225 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5226 LocalFree(buf);
5227 buf = NULL;
5229 value2.cbData = sizeof(encodedIPAddr);
5230 value2.pbData = (LPBYTE)encodedIPAddr;
5231 attr2.pszObjId = oid2;
5232 attr2.cValue = 1;
5233 attr2.rgValue = &value2;
5234 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5235 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5236 ctlEntry[1].cAttribute = 1;
5237 ctlEntry[1].rgAttribute = &attr2;
5238 info.cCTLEntry = 2;
5239 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5240 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5241 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5242 if (buf)
5244 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5245 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5246 LocalFree(buf);
5247 buf = NULL;
5251 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5252 const CTL_INFO *got)
5254 DWORD i, j, k;
5256 ok(expected->dwVersion == got->dwVersion,
5257 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5258 got->dwVersion);
5259 ok(expected->SubjectUsage.cUsageIdentifier ==
5260 got->SubjectUsage.cUsageIdentifier,
5261 "%s: expected %d usage identifiers, got %d\n", header,
5262 expected->SubjectUsage.cUsageIdentifier,
5263 got->SubjectUsage.cUsageIdentifier);
5264 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5265 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5266 got->SubjectUsage.rgpszUsageIdentifier[i]),
5267 "%s[%d]: expected %s, got %s\n", header, i,
5268 expected->SubjectUsage.rgpszUsageIdentifier[i],
5269 got->SubjectUsage.rgpszUsageIdentifier[i]);
5270 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5271 "%s: expected list identifier of %d bytes, got %d\n", header,
5272 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5273 if (expected->ListIdentifier.cbData)
5274 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5275 expected->ListIdentifier.cbData),
5276 "%s: unexpected list identifier value\n", header);
5277 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5278 "%s: expected sequence number of %d bytes, got %d\n", header,
5279 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5280 if (expected->SequenceNumber.cbData)
5281 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5282 expected->SequenceNumber.cbData),
5283 "%s: unexpected sequence number value\n", header);
5284 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5285 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5286 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5287 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5288 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5289 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5290 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5291 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5292 if (expected->SubjectAlgorithm.pszObjId &&
5293 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5294 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5295 expected->SubjectAlgorithm.pszObjId);
5296 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5297 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5298 got->SubjectAlgorithm.pszObjId),
5299 "%s: expected subject algorithm %s, got %s\n", header,
5300 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5301 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5302 got->SubjectAlgorithm.Parameters.cbData,
5303 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5304 expected->SubjectAlgorithm.Parameters.cbData,
5305 got->SubjectAlgorithm.Parameters.cbData);
5306 if (expected->SubjectAlgorithm.Parameters.cbData)
5307 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5308 got->SubjectAlgorithm.Parameters.pbData,
5309 expected->SubjectAlgorithm.Parameters.cbData),
5310 "%s: unexpected subject algorithm parameter value\n", header);
5311 ok(expected->cCTLEntry == got->cCTLEntry,
5312 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5313 got->cCTLEntry);
5314 for (i = 0; i < expected->cCTLEntry; i++)
5316 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5317 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5318 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5319 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5320 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5321 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5322 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5323 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5324 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5325 "%s[%d]: unexpected subject identifier value\n",
5326 header, i);
5327 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5329 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5330 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5331 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5332 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5333 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5334 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5336 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5337 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5338 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5339 header, i, j, k,
5340 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5341 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5342 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5343 ok(!memcmp(
5344 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5345 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5346 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5347 "%s[%d][%d][%d]: unexpected value\n",
5348 header, i, j, k);
5352 ok(expected->cExtension == got->cExtension,
5353 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5354 got->cExtension);
5355 for (i = 0; i < expected->cExtension; i++)
5357 ok(!strcmp(expected->rgExtension[i].pszObjId,
5358 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5359 header, i, expected->rgExtension[i].pszObjId,
5360 got->rgExtension[i].pszObjId);
5361 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5362 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5363 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5364 ok(expected->rgExtension[i].Value.cbData ==
5365 got->rgExtension[i].Value.cbData,
5366 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5367 header, i, expected->rgExtension[i].Value.cbData,
5368 got->rgExtension[i].Value.cbData);
5369 if (expected->rgExtension[i].Value.cbData)
5370 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5371 got->rgExtension[i].Value.pbData,
5372 expected->rgExtension[i].Value.cbData),
5373 "%s[%d]: unexpected extension value\n", header, i);
5377 static const BYTE signedCTL[] = {
5378 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5379 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5380 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5381 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5382 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5383 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5384 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5385 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5386 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5387 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5388 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5389 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5390 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5391 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5392 static const BYTE signedCTLWithCTLInnerContent[] = {
5393 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5394 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5395 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5396 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5397 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5398 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5399 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5400 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5401 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5402 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5403 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5404 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5405 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5406 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5407 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5408 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5409 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5410 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5411 0x57,0x6c,0x0b,0x47,0xb8 };
5413 static void test_decodeCTL(DWORD dwEncoding)
5415 static char oid1[] = "1.2.3";
5416 static char oid2[] = "1.5.6";
5417 static BYTE nullData[] = { 5,0 };
5418 char *pOid1 = oid1;
5419 BOOL ret;
5420 BYTE *buf = NULL;
5421 DWORD size = 0;
5422 CTL_INFO info;
5423 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5424 CTL_ENTRY ctlEntry[2];
5425 CRYPT_ATTRIBUTE attr1, attr2;
5426 CRYPT_ATTR_BLOB value1, value2;
5428 memset(&info, 0, sizeof(info));
5429 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5430 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5431 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5432 if (buf)
5434 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5435 LocalFree(buf);
5436 buf = NULL;
5438 info.dwVersion = 1;
5439 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5440 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5441 &size);
5442 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5443 if (buf)
5445 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5446 LocalFree(buf);
5447 buf = NULL;
5449 info.dwVersion = 0;
5450 info.SubjectUsage.cUsageIdentifier = 1;
5451 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5452 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5453 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5454 &buf, &size);
5455 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5456 if (buf)
5458 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5459 LocalFree(buf);
5460 buf = NULL;
5462 info.SubjectUsage.cUsageIdentifier = 0;
5463 info.ListIdentifier.cbData = sizeof(serialNum);
5464 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5465 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5466 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5467 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5468 if (buf)
5470 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5471 LocalFree(buf);
5472 buf = NULL;
5474 info.ListIdentifier.cbData = 0;
5475 info.SequenceNumber.cbData = sizeof(serialNum);
5476 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5477 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5478 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5479 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5480 if (buf)
5482 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5483 LocalFree(buf);
5484 buf = NULL;
5486 info.SequenceNumber.cbData = 0;
5487 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5488 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5489 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5490 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5491 if (buf)
5493 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5494 LocalFree(buf);
5495 buf = NULL;
5497 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5498 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5499 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5500 &buf, &size);
5501 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5502 if (buf)
5504 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5505 LocalFree(buf);
5506 buf = NULL;
5508 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5509 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5510 info.SubjectAlgorithm.pszObjId = oid2;
5511 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5512 info.SubjectAlgorithm.Parameters.pbData = nullData;
5513 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5514 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5515 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5516 if (buf)
5518 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5519 LocalFree(buf);
5520 buf = NULL;
5522 SetLastError(0xdeadbeef);
5523 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5524 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5525 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5526 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5527 GetLastError());
5528 info.SubjectAlgorithm.Parameters.cbData = 0;
5529 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5530 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5531 info.SubjectAlgorithm.pszObjId = oid2;
5532 info.SubjectAlgorithm.pszObjId = NULL;
5533 value1.cbData = sizeof(emptySequence);
5534 value1.pbData = (LPBYTE)emptySequence;
5535 attr1.pszObjId = oid1;
5536 attr1.cValue = 1;
5537 attr1.rgValue = &value1;
5538 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5539 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5540 ctlEntry[0].cAttribute = 1;
5541 ctlEntry[0].rgAttribute = &attr1;
5542 info.cCTLEntry = 1;
5543 info.rgCTLEntry = ctlEntry;
5544 SetLastError(0xdeadbeef);
5545 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5546 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5547 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5548 if (buf)
5550 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5551 LocalFree(buf);
5552 buf = NULL;
5554 value2.cbData = sizeof(encodedIPAddr);
5555 value2.pbData = (LPBYTE)encodedIPAddr;
5556 attr2.pszObjId = oid2;
5557 attr2.cValue = 1;
5558 attr2.rgValue = &value2;
5559 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5560 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5561 ctlEntry[1].cAttribute = 1;
5562 ctlEntry[1].rgAttribute = &attr2;
5563 info.cCTLEntry = 2;
5564 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5565 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5566 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5567 if (buf)
5569 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5570 LocalFree(buf);
5571 buf = NULL;
5573 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5574 SetLastError(0xdeadbeef);
5575 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5576 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5577 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5578 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5579 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5580 GetLastError());
5581 SetLastError(0xdeadbeef);
5582 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5583 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5584 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5585 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5586 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5587 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5588 GetLastError());
5591 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5592 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5593 0x03,0,0,0,0,0,0 };
5594 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5595 0xa0,0x01,0x01 };
5596 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5597 0x03,0x02,0x01,0x01 };
5598 static BYTE bogusDER[] = { 1 };
5600 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5602 BOOL ret;
5603 BYTE *buf = NULL;
5604 DWORD size = 0;
5605 CRYPT_CONTENT_INFO info = { 0 };
5606 char oid1[] = "1.2.3";
5608 if (0)
5610 /* Crashes on win9x */
5611 SetLastError(0xdeadbeef);
5612 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5613 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5614 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5615 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5617 SetLastError(0xdeadbeef);
5618 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5619 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5620 ok(!ret && (GetLastError() == E_INVALIDARG ||
5621 GetLastError() == OSS_LIMITED /* Win9x */),
5622 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5623 info.pszObjId = oid1;
5624 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5625 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5626 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5627 if (buf)
5629 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5630 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5631 LocalFree(buf);
5633 info.Content.pbData = bogusDER;
5634 info.Content.cbData = sizeof(bogusDER);
5635 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5636 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5637 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5638 if (buf)
5640 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5641 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5642 LocalFree(buf);
5644 info.Content.pbData = (BYTE *)ints[0].encoded;
5645 info.Content.cbData = ints[0].encoded[1] + 2;
5646 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5647 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5648 if (buf)
5650 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5651 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5652 LocalFree(buf);
5656 static const BYTE indefiniteSignedPKCSContent[] = {
5657 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5658 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5659 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5660 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5661 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5662 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5663 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5664 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5665 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5666 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5667 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5668 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5669 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5670 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5671 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5672 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5673 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5674 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5675 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5676 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5677 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5678 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5679 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5680 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5681 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5682 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5683 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5684 0x00,0x00,0x00,0x00,0x00,0x00 };
5686 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5688 BOOL ret;
5689 LPBYTE buf = NULL;
5690 DWORD size = 0;
5691 CRYPT_CONTENT_INFO *info;
5693 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5694 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5695 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5696 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5697 if (buf)
5699 info = (CRYPT_CONTENT_INFO *)buf;
5701 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5702 info->pszObjId);
5703 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5704 info->Content.cbData);
5705 LocalFree(buf);
5707 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5708 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5709 0, NULL, NULL, &size);
5710 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5711 SetLastError(0xdeadbeef);
5712 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5713 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5714 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5715 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5716 * I doubt an app depends on that.
5718 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5719 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5720 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5721 GetLastError());
5722 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5723 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5724 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5725 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5726 if (buf)
5728 info = (CRYPT_CONTENT_INFO *)buf;
5730 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5731 info->pszObjId);
5732 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5733 "Unexpected size %d\n", info->Content.cbData);
5734 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5735 info->Content.cbData), "Unexpected value\n");
5736 LocalFree(buf);
5738 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5739 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5740 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5741 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5742 if (buf)
5744 info = (CRYPT_CONTENT_INFO *)buf;
5746 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5747 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5748 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5749 info->Content.cbData);
5750 LocalFree(buf);
5754 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5755 0x00 };
5756 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5757 0x01 };
5758 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5759 0x02,0x01,0x01 };
5761 static void test_encodePKCSAttribute(DWORD dwEncoding)
5763 CRYPT_ATTRIBUTE attr = { 0 };
5764 BOOL ret;
5765 LPBYTE buf = NULL;
5766 DWORD size = 0;
5767 CRYPT_ATTR_BLOB blob;
5768 char oid[] = "1.2.3";
5770 if (0)
5772 /* Crashes on win9x */
5773 SetLastError(0xdeadbeef);
5774 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5775 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5776 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5777 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5779 SetLastError(0xdeadbeef);
5780 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5781 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5782 ok(!ret && (GetLastError() == E_INVALIDARG ||
5783 GetLastError() == OSS_LIMITED /* Win9x */),
5784 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5785 attr.pszObjId = oid;
5786 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5787 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5788 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5789 if (buf)
5791 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5792 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5793 LocalFree(buf);
5795 blob.cbData = sizeof(bogusDER);
5796 blob.pbData = bogusDER;
5797 attr.cValue = 1;
5798 attr.rgValue = &blob;
5799 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5800 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5801 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5802 if (buf)
5804 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5805 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5806 LocalFree(buf);
5808 blob.pbData = (BYTE *)ints[0].encoded;
5809 blob.cbData = ints[0].encoded[1] + 2;
5810 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5811 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5812 if (buf)
5814 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5815 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5816 LocalFree(buf);
5820 static void test_decodePKCSAttribute(DWORD dwEncoding)
5822 BOOL ret;
5823 LPBYTE buf = NULL;
5824 DWORD size = 0;
5825 CRYPT_ATTRIBUTE *attr;
5827 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5828 emptyPKCSAttr, sizeof(emptyPKCSAttr),
5829 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5830 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5831 if (buf)
5833 attr = (CRYPT_ATTRIBUTE *)buf;
5835 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5836 attr->pszObjId);
5837 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5838 LocalFree(buf);
5840 SetLastError(0xdeadbeef);
5841 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5842 bogusPKCSAttr, sizeof(bogusPKCSAttr),
5843 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5844 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5845 * I doubt an app depends on that.
5847 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5848 GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */),
5849 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5850 GetLastError());
5851 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5852 intPKCSAttr, sizeof(intPKCSAttr),
5853 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5854 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5855 if (buf)
5857 attr = (CRYPT_ATTRIBUTE *)buf;
5859 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5860 attr->pszObjId);
5861 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5862 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5863 "Unexpected size %d\n", attr->rgValue[0].cbData);
5864 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5865 attr->rgValue[0].cbData), "Unexpected value\n");
5866 LocalFree(buf);
5870 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5871 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5872 0x2a,0x03,0x31,0x00 };
5873 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5874 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5876 static void test_encodePKCSAttributes(DWORD dwEncoding)
5878 CRYPT_ATTRIBUTES attributes = { 0 };
5879 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5880 CRYPT_ATTR_BLOB blob;
5881 BOOL ret;
5882 LPBYTE buf = NULL;
5883 DWORD size = 0;
5884 char oid1[] = "1.2.3", oid2[] = "1.5.6";
5886 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5887 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5888 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5889 if (buf)
5891 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5892 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5893 LocalFree(buf);
5895 attributes.cAttr = 1;
5896 attributes.rgAttr = attr;
5897 SetLastError(0xdeadbeef);
5898 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5899 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5900 ok(!ret && (GetLastError() == E_INVALIDARG ||
5901 GetLastError() == OSS_LIMITED /* Win9x */),
5902 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5903 attr[0].pszObjId = oid1;
5904 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5905 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5906 if (buf)
5908 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5909 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5910 LocalFree(buf);
5912 attr[1].pszObjId = oid2;
5913 attr[1].cValue = 1;
5914 attr[1].rgValue = &blob;
5915 blob.pbData = (BYTE *)ints[0].encoded;
5916 blob.cbData = ints[0].encoded[1] + 2;
5917 attributes.cAttr = 2;
5918 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5919 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5920 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5921 if (buf)
5923 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5924 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5925 LocalFree(buf);
5929 static void test_decodePKCSAttributes(DWORD dwEncoding)
5931 BOOL ret;
5932 LPBYTE buf = NULL;
5933 DWORD size = 0;
5934 CRYPT_ATTRIBUTES *attributes;
5936 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5937 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5938 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5939 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5940 if (buf)
5942 attributes = (CRYPT_ATTRIBUTES *)buf;
5943 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5944 attributes->cAttr);
5945 LocalFree(buf);
5947 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5948 singlePKCSAttributes, sizeof(singlePKCSAttributes),
5949 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5950 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5951 if (buf)
5953 attributes = (CRYPT_ATTRIBUTES *)buf;
5954 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5955 attributes->cAttr);
5956 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5957 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5958 ok(attributes->rgAttr[0].cValue == 0,
5959 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5960 LocalFree(buf);
5962 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5963 doublePKCSAttributes, sizeof(doublePKCSAttributes),
5964 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5965 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5966 if (buf)
5968 attributes = (CRYPT_ATTRIBUTES *)buf;
5969 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5970 attributes->cAttr);
5971 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5972 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5973 ok(attributes->rgAttr[0].cValue == 0,
5974 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5975 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5976 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5977 ok(attributes->rgAttr[1].cValue == 1,
5978 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5979 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5980 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5981 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5982 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5983 LocalFree(buf);
5987 static const BYTE singleCapability[] = {
5988 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5989 static const BYTE twoCapabilities[] = {
5990 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5991 static const BYTE singleCapabilitywithNULL[] = {
5992 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5994 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5996 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5997 BOOL ret;
5998 LPBYTE buf = NULL;
5999 DWORD size = 0;
6000 CRYPT_SMIME_CAPABILITY capability[2];
6001 CRYPT_SMIME_CAPABILITIES capabilities;
6003 /* An empty capabilities is allowed */
6004 capabilities.cCapability = 0;
6005 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6006 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6007 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6008 if (buf)
6010 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6011 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6012 LocalFree(buf);
6014 /* A non-empty capabilities with an empty capability (lacking an OID) is
6015 * not allowed
6017 capability[0].pszObjId = NULL;
6018 capability[0].Parameters.cbData = 0;
6019 capabilities.cCapability = 1;
6020 capabilities.rgCapability = capability;
6021 SetLastError(0xdeadbeef);
6022 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6023 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6024 ok(!ret && (GetLastError() == E_INVALIDARG ||
6025 GetLastError() == OSS_LIMITED /* Win9x */),
6026 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6027 capability[0].pszObjId = oid1;
6028 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6029 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6030 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6031 if (buf)
6033 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6034 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6035 LocalFree(buf);
6037 capability[1].pszObjId = oid2;
6038 capability[1].Parameters.cbData = 0;
6039 capabilities.cCapability = 2;
6040 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6041 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6042 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6043 if (buf)
6045 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6046 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6047 LocalFree(buf);
6051 static void compareSMimeCapabilities(LPCSTR header,
6052 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6054 DWORD i;
6056 ok(got->cCapability == expected->cCapability,
6057 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6058 got->cCapability);
6059 for (i = 0; i < expected->cCapability; i++)
6061 ok(!strcmp(expected->rgCapability[i].pszObjId,
6062 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6063 header, i, expected->rgCapability[i].pszObjId,
6064 got->rgCapability[i].pszObjId);
6065 ok(expected->rgCapability[i].Parameters.cbData ==
6066 got->rgCapability[i].Parameters.cbData,
6067 "%s[%d]: expected %d bytes, got %d\n", header, i,
6068 expected->rgCapability[i].Parameters.cbData,
6069 got->rgCapability[i].Parameters.cbData);
6070 if (expected->rgCapability[i].Parameters.cbData)
6071 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6072 got->rgCapability[i].Parameters.pbData,
6073 expected->rgCapability[i].Parameters.cbData),
6074 "%s[%d]: unexpected value\n", header, i);
6078 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6080 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6081 BOOL ret;
6082 DWORD size = 0;
6083 CRYPT_SMIME_CAPABILITY capability[2];
6084 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6086 SetLastError(0xdeadbeef);
6087 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6088 emptySequence, sizeof(emptySequence),
6089 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6090 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6091 if (ret)
6093 capabilities.cCapability = 0;
6094 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6095 LocalFree(ptr);
6097 SetLastError(0xdeadbeef);
6098 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6099 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6100 &ptr, &size);
6101 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6102 if (ret)
6104 capability[0].pszObjId = oid1;
6105 capability[0].Parameters.cbData = 0;
6106 capabilities.cCapability = 1;
6107 capabilities.rgCapability = capability;
6108 compareSMimeCapabilities("single capability", &capabilities, ptr);
6109 LocalFree(ptr);
6111 SetLastError(0xdeadbeef);
6112 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6113 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6114 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6115 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6116 if (ret)
6118 BYTE NULLparam[] = {0x05, 0x00};
6119 capability[0].pszObjId = oid1;
6120 capability[0].Parameters.cbData = 2;
6121 capability[0].Parameters.pbData = NULLparam;
6122 capabilities.cCapability = 1;
6123 capabilities.rgCapability = capability;
6124 compareSMimeCapabilities("single capability with NULL", &capabilities,
6125 ptr);
6126 LocalFree(ptr);
6128 SetLastError(0xdeadbeef);
6129 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6130 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6131 &ptr, &size);
6132 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6133 if (ret)
6135 capability[0].Parameters.cbData = 0;
6136 capability[1].pszObjId = oid2;
6137 capability[1].Parameters.cbData = 0;
6138 capabilities.cCapability = 2;
6139 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6140 LocalFree(ptr);
6144 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6145 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6146 0x67 };
6147 static const BYTE minimalPKCSSigner[] = {
6148 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6149 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6150 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6151 static const BYTE PKCSSignerWithSerial[] = {
6152 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6153 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6154 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6155 0x00 };
6156 static const BYTE PKCSSignerWithHashAlgo[] = {
6157 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6158 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6159 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6160 0x00,0x04,0x00 };
6161 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6162 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6163 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6164 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6165 0x06,0x05,0x00,0x04,0x00 };
6166 static const BYTE PKCSSignerWithHash[] = {
6167 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6168 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6169 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6170 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6171 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6172 static const BYTE PKCSSignerWithAuthAttr[] = {
6173 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6174 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6175 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6176 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6177 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6178 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6179 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6181 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6183 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6184 BOOL ret;
6185 LPBYTE buf = NULL;
6186 DWORD size = 0;
6187 CMSG_SIGNER_INFO info = { 0 };
6188 char oid_common_name[] = szOID_COMMON_NAME;
6189 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6190 (LPBYTE)encodedCommonName };
6191 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6193 SetLastError(0xdeadbeef);
6194 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6195 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6196 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6198 skip("no PKCS7_SIGNER_INFO encode support\n");
6199 return;
6201 ok(!ret && (GetLastError() == E_INVALIDARG ||
6202 GetLastError() == OSS_LIMITED /* Win9x */),
6203 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6204 /* To be encoded, a signer must have an issuer at least, and the encoding
6205 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6206 * see decoding tests.)
6208 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6209 info.Issuer.pbData = encodedCommonNameNoNull;
6210 SetLastError(0xdeadbeef);
6211 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6212 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6213 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6214 ok(!ret && GetLastError() == E_INVALIDARG,
6215 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6216 else
6218 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6219 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6220 if (buf)
6222 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6223 if (size == sizeof(minimalPKCSSigner))
6224 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6225 else
6226 ok(0, "Unexpected value\n");
6227 LocalFree(buf);
6230 info.SerialNumber.cbData = sizeof(serialNum);
6231 info.SerialNumber.pbData = (BYTE *)serialNum;
6232 SetLastError(0xdeadbeef);
6233 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6234 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6235 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6236 ok(!ret && GetLastError() == E_INVALIDARG,
6237 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6238 else
6240 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6241 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6242 if (buf)
6244 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6245 size);
6246 if (size == sizeof(PKCSSignerWithSerial))
6247 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6248 "Unexpected value\n");
6249 else
6250 ok(0, "Unexpected value\n");
6251 LocalFree(buf);
6254 info.HashAlgorithm.pszObjId = oid1;
6255 SetLastError(0xdeadbeef);
6256 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6257 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6258 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6259 ok(!ret && GetLastError() == E_INVALIDARG,
6260 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6261 else
6263 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6264 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6265 if (buf)
6267 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6268 size);
6269 if (size == sizeof(PKCSSignerWithHashAlgo))
6270 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6271 "Unexpected value\n");
6272 else
6273 ok(0, "Unexpected value\n");
6274 LocalFree(buf);
6277 info.HashEncryptionAlgorithm.pszObjId = oid2;
6278 SetLastError(0xdeadbeef);
6279 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6280 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6281 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6282 ok(!ret && GetLastError() == E_INVALIDARG,
6283 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6284 else
6286 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6287 if (buf)
6289 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6290 "Unexpected size %d\n", size);
6291 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6292 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6293 "Unexpected value\n");
6294 else
6295 ok(0, "Unexpected value\n");
6296 LocalFree(buf);
6299 info.EncryptedHash.cbData = sizeof(hash);
6300 info.EncryptedHash.pbData = (BYTE *)hash;
6301 SetLastError(0xdeadbeef);
6302 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6303 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6304 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6305 ok(!ret && GetLastError() == E_INVALIDARG,
6306 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6307 else
6309 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6310 if (buf)
6312 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6313 size);
6314 if (size == sizeof(PKCSSignerWithHash))
6315 ok(!memcmp(buf, PKCSSignerWithHash, size),
6316 "Unexpected value\n");
6317 else
6318 ok(0, "Unexpected value\n");
6319 LocalFree(buf);
6322 info.AuthAttrs.cAttr = 1;
6323 info.AuthAttrs.rgAttr = &attr;
6324 SetLastError(0xdeadbeef);
6325 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6326 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6327 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6328 ok(!ret && GetLastError() == E_INVALIDARG,
6329 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6330 else
6332 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6333 if (buf)
6335 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6336 size);
6337 if (size == sizeof(PKCSSignerWithAuthAttr))
6338 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6339 "Unexpected value\n");
6340 else
6341 ok(0, "Unexpected value\n");
6342 LocalFree(buf);
6347 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6349 BOOL ret;
6350 LPBYTE buf = NULL;
6351 DWORD size = 0;
6352 CMSG_SIGNER_INFO *info;
6354 /* A PKCS signer can't be decoded without a serial number. */
6355 SetLastError(0xdeadbeef);
6356 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6357 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6358 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6359 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6360 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6361 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6362 GetLastError());
6363 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6364 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6365 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6366 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6367 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6368 if (buf)
6370 info = (CMSG_SIGNER_INFO *)buf;
6371 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6372 info->dwVersion);
6373 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6374 "Unexpected size %d\n", info->Issuer.cbData);
6375 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6376 info->Issuer.cbData), "Unexpected value\n");
6377 ok(info->SerialNumber.cbData == sizeof(serialNum),
6378 "Unexpected size %d\n", info->SerialNumber.cbData);
6379 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6380 "Unexpected value\n");
6381 LocalFree(buf);
6383 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6384 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6385 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6386 if (buf)
6388 info = (CMSG_SIGNER_INFO *)buf;
6389 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6390 info->dwVersion);
6391 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6392 "Unexpected size %d\n", info->Issuer.cbData);
6393 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6394 info->Issuer.cbData), "Unexpected value\n");
6395 ok(info->SerialNumber.cbData == sizeof(serialNum),
6396 "Unexpected size %d\n", info->SerialNumber.cbData);
6397 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6398 "Unexpected value\n");
6399 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6400 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6401 LocalFree(buf);
6403 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6404 PKCSSignerWithHashAndEncryptionAlgo,
6405 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6406 NULL, &buf, &size);
6407 if (buf)
6409 info = (CMSG_SIGNER_INFO *)buf;
6410 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6411 info->dwVersion);
6412 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6413 "Unexpected size %d\n", info->Issuer.cbData);
6414 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6415 info->Issuer.cbData), "Unexpected value\n");
6416 ok(info->SerialNumber.cbData == sizeof(serialNum),
6417 "Unexpected size %d\n", info->SerialNumber.cbData);
6418 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6419 "Unexpected value\n");
6420 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6421 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6422 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6423 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6424 LocalFree(buf);
6426 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6427 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6428 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6429 if (buf)
6431 info = (CMSG_SIGNER_INFO *)buf;
6432 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6433 info->dwVersion);
6434 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6435 "Unexpected size %d\n", info->Issuer.cbData);
6436 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6437 info->Issuer.cbData), "Unexpected value\n");
6438 ok(info->SerialNumber.cbData == sizeof(serialNum),
6439 "Unexpected size %d\n", info->SerialNumber.cbData);
6440 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6441 "Unexpected value\n");
6442 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6443 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6444 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6445 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6446 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6447 info->EncryptedHash.cbData);
6448 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6449 "Unexpected value\n");
6450 LocalFree(buf);
6452 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6453 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6454 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6455 if (buf)
6457 info = (CMSG_SIGNER_INFO *)buf;
6458 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6459 info->AuthAttrs.cAttr);
6460 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6461 "Expected %s, got %s\n", szOID_COMMON_NAME,
6462 info->AuthAttrs.rgAttr[0].pszObjId);
6463 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6464 info->AuthAttrs.rgAttr[0].cValue);
6465 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6466 sizeof(encodedCommonName), "Unexpected size %d\n",
6467 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6468 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6469 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6470 LocalFree(buf);
6474 static const BYTE CMSSignerWithKeyId[] = {
6475 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6476 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6478 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6480 BOOL ret;
6481 LPBYTE buf = NULL;
6482 DWORD size = 0;
6483 CMSG_CMS_SIGNER_INFO info = { 0 };
6484 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6486 SetLastError(0xdeadbeef);
6487 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6488 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6489 ok(!ret, "Expected failure, got %d\n", ret);
6490 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6492 skip("no CMS_SIGNER_INFO encode support\n");
6493 return;
6495 ok(GetLastError() == E_INVALIDARG,
6496 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6497 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6498 SetLastError(0xdeadbeef);
6499 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6500 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6501 ok(!ret, "Expected failure, got %d\n", ret);
6502 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6504 skip("no CMS_SIGNER_INFO encode support\n");
6505 return;
6507 ok(GetLastError() == E_INVALIDARG,
6508 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6509 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6510 * be a key id or a issuer serial number with at least the issuer set, and
6511 * the encoding must include PKCS_7_ASN_ENCODING.
6512 * (That isn't enough to be decoded, see decoding tests.)
6514 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6515 sizeof(encodedCommonNameNoNull);
6516 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6517 SetLastError(0xdeadbeef);
6518 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6519 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6520 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6521 ok(!ret && GetLastError() == E_INVALIDARG,
6522 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6523 else
6525 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6526 if (buf)
6528 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6529 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6530 LocalFree(buf);
6533 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6534 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6535 SetLastError(0xdeadbeef);
6536 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6537 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6538 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6539 ok(!ret && GetLastError() == E_INVALIDARG,
6540 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6541 else
6543 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6544 if (buf)
6546 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6547 size);
6548 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6549 LocalFree(buf);
6552 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6553 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6554 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6555 SetLastError(0xdeadbeef);
6556 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6557 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6558 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6559 ok(!ret && GetLastError() == E_INVALIDARG,
6560 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6561 else
6563 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6564 if (buf)
6566 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6567 size);
6568 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6569 LocalFree(buf);
6572 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6573 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6574 * (see RFC 3852, section 5.3.)
6576 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6577 U(info.SignerId).HashId.cbData = sizeof(hash);
6578 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6579 SetLastError(0xdeadbeef);
6580 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6581 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6582 ok(!ret && GetLastError() == E_INVALIDARG,
6583 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6584 /* Now with a hash algo */
6585 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6586 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6587 sizeof(encodedCommonNameNoNull);
6588 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6589 info.HashAlgorithm.pszObjId = oid1;
6590 SetLastError(0xdeadbeef);
6591 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6592 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6593 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6594 ok(!ret && GetLastError() == E_INVALIDARG,
6595 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6596 else
6598 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6599 if (buf)
6601 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6602 size);
6603 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6604 "Unexpected value\n");
6605 LocalFree(buf);
6608 info.HashEncryptionAlgorithm.pszObjId = oid2;
6609 SetLastError(0xdeadbeef);
6610 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6611 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6612 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6613 ok(!ret && GetLastError() == E_INVALIDARG,
6614 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6615 else
6617 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6618 if (buf)
6620 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6621 "Unexpected size %d\n", size);
6622 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6623 "Unexpected value\n");
6624 LocalFree(buf);
6627 info.EncryptedHash.cbData = sizeof(hash);
6628 info.EncryptedHash.pbData = (BYTE *)hash;
6629 SetLastError(0xdeadbeef);
6630 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6631 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6632 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6633 ok(!ret && GetLastError() == E_INVALIDARG,
6634 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6635 else
6637 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6638 if (buf)
6640 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6641 size);
6642 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6643 LocalFree(buf);
6648 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6650 BOOL ret;
6651 LPBYTE buf = NULL;
6652 DWORD size = 0;
6653 CMSG_CMS_SIGNER_INFO *info;
6654 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6656 /* A CMS signer can't be decoded without a serial number. */
6657 SetLastError(0xdeadbeef);
6658 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6659 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6660 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6661 ok(!ret, "expected failure\n");
6662 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6664 skip("no CMS_SIGNER_INFO decode support\n");
6665 return;
6667 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6668 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6669 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6670 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6671 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6672 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6673 if (buf)
6675 info = (CMSG_CMS_SIGNER_INFO *)buf;
6676 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6677 info->dwVersion);
6678 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6679 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6680 info->SignerId.dwIdChoice);
6681 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6682 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6683 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6684 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6685 encodedCommonNameNoNull,
6686 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6687 "Unexpected value\n");
6688 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6689 sizeof(serialNum), "Unexpected size %d\n",
6690 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6691 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6692 serialNum, sizeof(serialNum)), "Unexpected value\n");
6693 LocalFree(buf);
6695 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6696 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6697 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6698 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6699 if (buf)
6701 info = (CMSG_CMS_SIGNER_INFO *)buf;
6702 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6703 info->dwVersion);
6704 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6705 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6706 info->SignerId.dwIdChoice);
6707 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6708 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6709 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6710 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6711 encodedCommonNameNoNull,
6712 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6713 "Unexpected value\n");
6714 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6715 sizeof(serialNum), "Unexpected size %d\n",
6716 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6717 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6718 serialNum, sizeof(serialNum)), "Unexpected value\n");
6719 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6720 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6721 LocalFree(buf);
6723 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6724 PKCSSignerWithHashAndEncryptionAlgo,
6725 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6726 NULL, &buf, &size);
6727 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6728 if (buf)
6730 info = (CMSG_CMS_SIGNER_INFO *)buf;
6731 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6732 info->dwVersion);
6733 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6734 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6735 info->SignerId.dwIdChoice);
6736 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6737 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6738 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6739 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6740 encodedCommonNameNoNull,
6741 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6742 "Unexpected value\n");
6743 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6744 sizeof(serialNum), "Unexpected size %d\n",
6745 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6746 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6747 serialNum, sizeof(serialNum)), "Unexpected value\n");
6748 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6749 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6750 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6751 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6752 LocalFree(buf);
6754 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6755 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6756 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6757 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6758 if (buf)
6760 info = (CMSG_CMS_SIGNER_INFO *)buf;
6761 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6762 info->dwVersion);
6763 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6764 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6765 info->SignerId.dwIdChoice);
6766 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6767 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6768 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6769 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6770 encodedCommonNameNoNull,
6771 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6772 "Unexpected value\n");
6773 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6774 sizeof(serialNum), "Unexpected size %d\n",
6775 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6776 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6777 serialNum, sizeof(serialNum)), "Unexpected value\n");
6778 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6779 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6780 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6781 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6782 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6783 info->EncryptedHash.cbData);
6784 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6785 "Unexpected value\n");
6786 LocalFree(buf);
6788 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6789 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6790 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6791 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6792 if (buf)
6794 info = (CMSG_CMS_SIGNER_INFO *)buf;
6795 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6796 info->dwVersion);
6797 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6798 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6799 info->SignerId.dwIdChoice);
6800 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6801 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6802 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6803 "Unexpected value\n");
6804 LocalFree(buf);
6808 static BYTE emptyDNSPermittedConstraints[] = {
6809 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6810 static BYTE emptyDNSExcludedConstraints[] = {
6811 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6812 static BYTE DNSExcludedConstraints[] = {
6813 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6814 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6815 static BYTE permittedAndExcludedConstraints[] = {
6816 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6817 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6818 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6819 static BYTE permittedAndExcludedWithMinConstraints[] = {
6820 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6821 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6822 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6823 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6824 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6825 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6826 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6828 static void test_encodeNameConstraints(DWORD dwEncoding)
6830 BOOL ret;
6831 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6832 CERT_GENERAL_SUBTREE permitted = { { 0 } };
6833 CERT_GENERAL_SUBTREE excluded = { { 0 } };
6834 LPBYTE buf;
6835 DWORD size;
6837 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6838 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6839 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6841 skip("no X509_NAME_CONSTRAINTS encode support\n");
6842 return;
6844 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6845 if (ret)
6847 ok(size == sizeof(emptySequence), "Unexpected size\n");
6848 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6849 LocalFree(buf);
6851 constraints.cPermittedSubtree = 1;
6852 constraints.rgPermittedSubtree = &permitted;
6853 SetLastError(0xdeadbeef);
6854 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6855 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6856 ok(!ret && GetLastError() == E_INVALIDARG,
6857 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6858 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6859 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6860 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6861 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6862 if (ret)
6864 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6865 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6866 "Unexpected value\n");
6867 LocalFree(buf);
6869 constraints.cPermittedSubtree = 0;
6870 constraints.cExcludedSubtree = 1;
6871 constraints.rgExcludedSubtree = &excluded;
6872 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6873 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6874 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6875 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6876 if (ret)
6878 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6879 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6880 "Unexpected value\n");
6881 LocalFree(buf);
6883 U(excluded.Base).pwszURL = (LPWSTR)url;
6884 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6885 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6886 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6887 if (ret)
6889 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6890 ok(!memcmp(buf, DNSExcludedConstraints, size),
6891 "Unexpected value\n");
6892 LocalFree(buf);
6894 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6895 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6896 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6897 constraints.cPermittedSubtree = 1;
6898 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6899 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6900 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6901 if (ret)
6903 ok(size == sizeof(permittedAndExcludedConstraints),
6904 "Unexpected size\n");
6905 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6906 "Unexpected value\n");
6907 LocalFree(buf);
6909 permitted.dwMinimum = 5;
6910 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6911 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6912 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6913 if (ret)
6915 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6916 "Unexpected size\n");
6917 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6918 "Unexpected value\n");
6919 LocalFree(buf);
6921 permitted.fMaximum = TRUE;
6922 permitted.dwMaximum = 3;
6923 SetLastError(0xdeadbeef);
6924 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6925 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6926 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6927 if (ret)
6929 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6930 "Unexpected size\n");
6931 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6932 "Unexpected value\n");
6933 LocalFree(buf);
6937 struct EncodedNameConstraints
6939 CRYPT_DATA_BLOB encoded;
6940 CERT_NAME_CONSTRAINTS_INFO constraints;
6943 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6944 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6945 static CERT_GENERAL_SUBTREE DNSSubtree = {
6946 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6947 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6948 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6949 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6950 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6951 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6952 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6954 struct EncodedNameConstraints encodedNameConstraints[] = {
6955 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6956 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6957 { 1, &emptyDNSSubtree, 0, NULL } },
6958 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6959 { 0, NULL, 1, &emptyDNSSubtree } },
6960 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6961 { 0, NULL, 1, &DNSSubtree } },
6962 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6963 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6964 { { sizeof(permittedAndExcludedWithMinConstraints),
6965 permittedAndExcludedWithMinConstraints },
6966 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6967 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6968 permittedAndExcludedWithMinMaxConstraints },
6969 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6972 static void test_decodeNameConstraints(DWORD dwEncoding)
6974 BOOL ret;
6975 DWORD i;
6976 CERT_NAME_CONSTRAINTS_INFO *constraints;
6978 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6979 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6980 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6981 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6982 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6983 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6984 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6985 for (i = 0;
6986 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6987 i++)
6989 DWORD size;
6991 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6992 encodedNameConstraints[i].encoded.pbData,
6993 encodedNameConstraints[i].encoded.cbData,
6994 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6995 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6997 skip("no X509_NAME_CONSTRAINTS decode support\n");
6998 return;
7000 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7001 if (ret)
7003 DWORD j;
7005 if (constraints->cPermittedSubtree !=
7006 encodedNameConstraints[i].constraints.cPermittedSubtree)
7007 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7008 encodedNameConstraints[i].constraints.cPermittedSubtree,
7009 constraints->cPermittedSubtree);
7010 if (constraints->cPermittedSubtree ==
7011 encodedNameConstraints[i].constraints.cPermittedSubtree)
7013 for (j = 0; j < constraints->cPermittedSubtree; j++)
7015 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7016 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7019 if (constraints->cExcludedSubtree !=
7020 encodedNameConstraints[i].constraints.cExcludedSubtree)
7021 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7022 encodedNameConstraints[i].constraints.cExcludedSubtree,
7023 constraints->cExcludedSubtree);
7024 if (constraints->cExcludedSubtree ==
7025 encodedNameConstraints[i].constraints.cExcludedSubtree)
7027 for (j = 0; j < constraints->cExcludedSubtree; j++)
7029 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7030 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7033 LocalFree(constraints);
7038 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7039 'n','o','t','i','c','e',0 };
7040 static const BYTE noticeWithDisplayText[] = {
7041 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7042 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7043 0x00,0x69,0x00,0x63,0x00,0x65
7045 static char org[] = "Wine";
7046 static int noticeNumbers[] = { 2,3 };
7047 static BYTE noticeWithReference[] = {
7048 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7049 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7050 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7051 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7054 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7056 BOOL ret;
7057 LPBYTE buf;
7058 DWORD size;
7059 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7060 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7062 memset(&notice, 0, sizeof(notice));
7063 ret = pCryptEncodeObjectEx(dwEncoding,
7064 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7065 NULL, &buf, &size);
7066 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7068 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7069 return;
7071 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7072 if (ret)
7074 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7075 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7076 LocalFree(buf);
7078 notice.pszDisplayText = noticeText;
7079 ret = pCryptEncodeObjectEx(dwEncoding,
7080 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7081 NULL, &buf, &size);
7082 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7083 if (ret)
7085 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7086 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7087 LocalFree(buf);
7089 reference.pszOrganization = org;
7090 reference.cNoticeNumbers = 2;
7091 reference.rgNoticeNumbers = noticeNumbers;
7092 notice.pNoticeReference = &reference;
7093 ret = pCryptEncodeObjectEx(dwEncoding,
7094 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7095 NULL, &buf, &size);
7096 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7097 if (ret)
7099 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7100 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7101 LocalFree(buf);
7105 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7107 BOOL ret;
7108 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7109 DWORD size;
7111 ret = pCryptDecodeObjectEx(dwEncoding,
7112 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7113 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7114 &notice, &size);
7115 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7117 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7118 return;
7120 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7121 if (ret)
7123 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7124 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7125 LocalFree(notice);
7127 ret = pCryptDecodeObjectEx(dwEncoding,
7128 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7129 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7130 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7131 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7132 if (ret)
7134 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7135 "unexpected display text\n");
7136 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7137 LocalFree(notice);
7139 ret = pCryptDecodeObjectEx(dwEncoding,
7140 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7141 noticeWithReference, sizeof(noticeWithReference),
7142 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7143 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7144 if (ret)
7146 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7147 "unexpected display text\n");
7148 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7149 if (notice->pNoticeReference)
7151 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7152 "unexpected organization %s\n",
7153 notice->pNoticeReference->pszOrganization);
7154 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7155 "expected 2 notice numbers, got %d\n",
7156 notice->pNoticeReference->cNoticeNumbers);
7157 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7158 "unexpected notice number %d\n",
7159 notice->pNoticeReference->rgNoticeNumbers[0]);
7160 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7161 "unexpected notice number %d\n",
7162 notice->pNoticeReference->rgNoticeNumbers[1]);
7164 LocalFree(notice);
7168 static char oid_any_policy[] = "2.5.29.32.0";
7169 static const BYTE policiesWithAnyPolicy[] = {
7170 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7172 static char oid1[] = "1.2.3";
7173 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7174 static const BYTE twoPolicies[] = {
7175 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7176 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7177 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7178 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7179 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7180 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7183 static void test_encodeCertPolicies(DWORD dwEncoding)
7185 BOOL ret;
7186 CERT_POLICIES_INFO info;
7187 CERT_POLICY_INFO policy[2];
7188 CERT_POLICY_QUALIFIER_INFO qualifier;
7189 LPBYTE buf;
7190 DWORD size;
7192 memset(&info, 0, sizeof(info));
7193 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7194 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7195 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7196 if (ret)
7198 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7199 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7200 LocalFree(buf);
7202 memset(policy, 0, sizeof(policy));
7203 info.cPolicyInfo = 1;
7204 info.rgPolicyInfo = policy;
7205 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7206 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7207 ok(!ret && (GetLastError() == E_INVALIDARG ||
7208 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7209 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7210 policy[0].pszPolicyIdentifier = oid_any_policy;
7211 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7212 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7213 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7214 if (ret)
7216 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7217 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7218 LocalFree(buf);
7220 policy[1].pszPolicyIdentifier = oid1;
7221 memset(&qualifier, 0, sizeof(qualifier));
7222 qualifier.pszPolicyQualifierId = oid_user_notice;
7223 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7224 qualifier.Qualifier.pbData = noticeWithReference;
7225 policy[1].cPolicyQualifier = 1;
7226 policy[1].rgPolicyQualifier = &qualifier;
7227 info.cPolicyInfo = 2;
7228 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7229 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7230 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7231 if (ret)
7233 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7234 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7235 LocalFree(buf);
7239 static void test_decodeCertPolicies(DWORD dwEncoding)
7241 BOOL ret;
7242 CERT_POLICIES_INFO *info;
7243 DWORD size;
7245 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7246 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7247 &info, &size);
7248 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7249 if (ret)
7251 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7252 info->cPolicyInfo);
7253 LocalFree(info);
7255 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7256 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7257 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7258 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7259 if (ret)
7261 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7262 info->cPolicyInfo);
7263 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7264 "unexpected policy id %s\n",
7265 info->rgPolicyInfo[0].pszPolicyIdentifier);
7266 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7267 "unexpected policy qualifier count %d\n",
7268 info->rgPolicyInfo[0].cPolicyQualifier);
7269 LocalFree(info);
7271 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7272 twoPolicies, sizeof(twoPolicies),
7273 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7274 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7275 if (ret)
7277 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7278 info->cPolicyInfo);
7279 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7280 "unexpected policy id %s\n",
7281 info->rgPolicyInfo[0].pszPolicyIdentifier);
7282 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7283 "unexpected policy qualifier count %d\n",
7284 info->rgPolicyInfo[0].cPolicyQualifier);
7285 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7286 "unexpected policy id %s\n",
7287 info->rgPolicyInfo[1].pszPolicyIdentifier);
7288 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7289 "unexpected policy qualifier count %d\n",
7290 info->rgPolicyInfo[1].cPolicyQualifier);
7291 ok(!strcmp(
7292 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7293 oid_user_notice), "unexpected policy qualifier id %s\n",
7294 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7295 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7296 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7297 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7298 ok(!memcmp(
7299 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7300 noticeWithReference, sizeof(noticeWithReference)),
7301 "unexpected qualifier value\n");
7302 LocalFree(info);
7306 /* Free *pInfo with HeapFree */
7307 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7309 BOOL ret;
7310 DWORD size = 0;
7311 HCRYPTKEY key;
7313 /* This crashes
7314 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7316 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7317 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7318 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7319 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7320 &size);
7321 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7322 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7323 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7324 NULL, &size);
7325 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7326 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7327 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7328 0, NULL, NULL, &size);
7329 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7330 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7331 /* Test with no key */
7332 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7333 0, NULL, NULL, &size);
7334 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7335 GetLastError());
7336 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7337 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7338 if (ret)
7340 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7341 NULL, 0, NULL, NULL, &size);
7342 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7343 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7344 if (*pInfo)
7346 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7347 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7348 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7349 GetLastError());
7350 if (ret)
7352 /* By default (we passed NULL as the OID) the OID is
7353 * szOID_RSA_RSA.
7355 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7356 "Expected %s, got %s\n", szOID_RSA_RSA,
7357 (*pInfo)->Algorithm.pszObjId);
7361 CryptDestroyKey(key);
7364 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7365 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7366 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7367 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7368 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7369 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7370 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7371 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7372 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7373 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7374 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7375 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7376 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7377 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7378 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7379 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7380 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7381 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7382 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7383 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7384 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7385 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7386 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7387 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7388 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7390 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7392 BOOL ret;
7393 HCRYPTKEY key;
7394 PCCERT_CONTEXT context;
7395 DWORD dwSize;
7396 ALG_ID ai;
7398 /* These crash
7399 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7400 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7401 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7402 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7403 NULL);
7405 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7406 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7407 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7408 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7409 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7410 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7411 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7412 &key);
7413 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7414 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7416 /* Export key with standard algorithm (CALG_RSA_KEYX) */
7417 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7418 &key);
7419 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7421 dwSize = sizeof(ai);
7422 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7423 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7424 if(ret)
7426 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7427 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7430 CryptDestroyKey(key);
7432 /* Repeat with forced algorithm */
7433 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7434 &key);
7435 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7437 dwSize = sizeof(ai);
7438 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7439 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7440 if(ret)
7442 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7443 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7446 CryptDestroyKey(key);
7448 /* Test importing a public key from a certificate context */
7449 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7450 sizeof(expiredCert));
7451 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7452 GetLastError());
7453 if (context)
7455 ok(!strcmp(szOID_RSA_RSA,
7456 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7457 "Expected %s, got %s\n", szOID_RSA_RSA,
7458 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7459 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7460 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7461 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7462 CryptDestroyKey(key);
7463 CertFreeCertificateContext(context);
7467 static const char cspName[] = "WineCryptTemp";
7469 static void testPortPublicKeyInfo(void)
7471 HCRYPTPROV csp;
7472 BOOL ret;
7473 PCERT_PUBLIC_KEY_INFO info = NULL;
7475 /* Just in case a previous run failed, delete this thing */
7476 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7477 CRYPT_DELETEKEYSET);
7478 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7479 CRYPT_NEWKEYSET);
7481 testExportPublicKey(csp, &info);
7482 testImportPublicKey(csp, info);
7484 HeapFree(GetProcessHeap(), 0, info);
7485 CryptReleaseContext(csp, 0);
7486 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7487 CRYPT_DELETEKEYSET);
7490 START_TEST(encode)
7492 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7493 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7494 HMODULE hCrypt32;
7495 DWORD i;
7497 hCrypt32 = GetModuleHandleA("crypt32.dll");
7498 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7499 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7500 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7502 skip("CryptDecodeObjectEx() is not available\n");
7503 return;
7506 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7508 test_encodeInt(encodings[i]);
7509 test_decodeInt(encodings[i]);
7510 test_encodeEnumerated(encodings[i]);
7511 test_decodeEnumerated(encodings[i]);
7512 test_encodeFiletime(encodings[i]);
7513 test_decodeFiletime(encodings[i]);
7514 test_encodeName(encodings[i]);
7515 test_decodeName(encodings[i]);
7516 test_encodeUnicodeName(encodings[i]);
7517 test_decodeUnicodeName(encodings[i]);
7518 test_encodeNameValue(encodings[i]);
7519 test_decodeNameValue(encodings[i]);
7520 test_encodeUnicodeNameValue(encodings[i]);
7521 test_decodeUnicodeNameValue(encodings[i]);
7522 test_encodeAltName(encodings[i]);
7523 test_decodeAltName(encodings[i]);
7524 test_encodeOctets(encodings[i]);
7525 test_decodeOctets(encodings[i]);
7526 test_encodeBits(encodings[i]);
7527 test_decodeBits(encodings[i]);
7528 test_encodeBasicConstraints(encodings[i]);
7529 test_decodeBasicConstraints(encodings[i]);
7530 test_encodeRsaPublicKey(encodings[i]);
7531 test_decodeRsaPublicKey(encodings[i]);
7532 test_encodeSequenceOfAny(encodings[i]);
7533 test_decodeSequenceOfAny(encodings[i]);
7534 test_encodeExtensions(encodings[i]);
7535 test_decodeExtensions(encodings[i]);
7536 test_encodePublicKeyInfo(encodings[i]);
7537 test_decodePublicKeyInfo(encodings[i]);
7538 test_encodeCertToBeSigned(encodings[i]);
7539 test_decodeCertToBeSigned(encodings[i]);
7540 test_encodeCert(encodings[i]);
7541 test_decodeCert(encodings[i]);
7542 test_encodeCRLDistPoints(encodings[i]);
7543 test_decodeCRLDistPoints(encodings[i]);
7544 test_encodeCRLIssuingDistPoint(encodings[i]);
7545 test_decodeCRLIssuingDistPoint(encodings[i]);
7546 test_encodeCRLToBeSigned(encodings[i]);
7547 test_decodeCRLToBeSigned(encodings[i]);
7548 test_encodeEnhancedKeyUsage(encodings[i]);
7549 test_decodeEnhancedKeyUsage(encodings[i]);
7550 test_encodeAuthorityKeyId(encodings[i]);
7551 test_decodeAuthorityKeyId(encodings[i]);
7552 test_encodeAuthorityKeyId2(encodings[i]);
7553 test_decodeAuthorityKeyId2(encodings[i]);
7554 test_encodeAuthorityInfoAccess(encodings[i]);
7555 test_decodeAuthorityInfoAccess(encodings[i]);
7556 test_encodeCTL(encodings[i]);
7557 test_decodeCTL(encodings[i]);
7558 test_encodePKCSContentInfo(encodings[i]);
7559 test_decodePKCSContentInfo(encodings[i]);
7560 test_encodePKCSAttribute(encodings[i]);
7561 test_decodePKCSAttribute(encodings[i]);
7562 test_encodePKCSAttributes(encodings[i]);
7563 test_decodePKCSAttributes(encodings[i]);
7564 test_encodePKCSSMimeCapabilities(encodings[i]);
7565 test_decodePKCSSMimeCapabilities(encodings[i]);
7566 test_encodePKCSSignerInfo(encodings[i]);
7567 test_decodePKCSSignerInfo(encodings[i]);
7568 test_encodeCMSSignerInfo(encodings[i]);
7569 test_decodeCMSSignerInfo(encodings[i]);
7570 test_encodeNameConstraints(encodings[i]);
7571 test_decodeNameConstraints(encodings[i]);
7572 test_encodePolicyQualifierUserNotice(encodings[i]);
7573 test_decodePolicyQualifierUserNotice(encodings[i]);
7574 test_encodeCertPolicies(encodings[i]);
7575 test_decodeCertPolicies(encodings[i]);
7577 testPortPublicKeyInfo();