push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / crypt32 / tests / encode.c
blob3e99800638c24a4a7b3a441b65964a3a17c5a6cb
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 },
1965 static void test_encodeBits(DWORD dwEncoding)
1967 DWORD i;
1969 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1971 CRYPT_BIT_BLOB blob;
1972 BOOL ret;
1973 BYTE *buf = NULL;
1974 DWORD bufSize = 0;
1976 blob.cbData = sizeof(bytesToEncode);
1977 blob.pbData = (BYTE *)bytesToEncode;
1978 blob.cUnusedBits = bits[i].cUnusedBits;
1979 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1980 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1981 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1982 if (buf)
1984 ok(bufSize == bits[i].encoded[1] + 2,
1985 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
1986 bits[i].encoded[1] + 2);
1987 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1988 "%d: Unexpected value\n", i);
1989 LocalFree(buf);
1994 static void test_decodeBits(DWORD dwEncoding)
1996 static const BYTE ber[] = "\x03\x02\x01\xff";
1997 static const BYTE berDecoded = 0xfe;
1998 DWORD i;
1999 BOOL ret;
2000 BYTE *buf = NULL;
2001 DWORD bufSize = 0;
2003 /* normal cases */
2004 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2006 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2007 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2008 &bufSize);
2009 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2010 if (buf)
2012 CRYPT_BIT_BLOB *blob;
2014 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2015 "Got unexpected size %d\n", bufSize);
2016 blob = (CRYPT_BIT_BLOB *)buf;
2017 ok(blob->cbData == bits[i].cbDecoded,
2018 "Got unexpected length %d, expected %d\n", blob->cbData,
2019 bits[i].cbDecoded);
2020 if (blob->cbData && bits[i].cbDecoded)
2021 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2022 "Unexpected value\n");
2023 LocalFree(buf);
2026 /* special case: check that something that's valid in BER but not in DER
2027 * decodes successfully
2029 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2030 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2031 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2032 if (buf)
2034 CRYPT_BIT_BLOB *blob;
2036 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2037 "Got unexpected size %d\n", bufSize);
2038 blob = (CRYPT_BIT_BLOB *)buf;
2039 ok(blob->cbData == sizeof(berDecoded),
2040 "Got unexpected length %d\n", blob->cbData);
2041 if (blob->cbData)
2042 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2043 LocalFree(buf);
2047 struct Constraints2
2049 CERT_BASIC_CONSTRAINTS2_INFO info;
2050 const BYTE *encoded;
2053 static const unsigned char bin59[] = { 0x30,0x00 };
2054 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2055 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2056 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2057 static const struct Constraints2 constraints2[] = {
2058 /* empty constraints */
2059 { { FALSE, FALSE, 0}, bin59 },
2060 /* can be a CA */
2061 { { TRUE, FALSE, 0}, bin60 },
2062 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2063 * but that's not the case
2065 { { FALSE, TRUE, 0}, bin61 },
2066 /* can be a CA and has path length constraints set */
2067 { { TRUE, TRUE, 1}, bin62 },
2070 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2071 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2072 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2073 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2074 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2075 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2076 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2077 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2078 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2079 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2081 static void test_encodeBasicConstraints(DWORD dwEncoding)
2083 DWORD i, bufSize = 0;
2084 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2085 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2086 (LPBYTE)encodedDomainName };
2087 BOOL ret;
2088 BYTE *buf = NULL;
2090 /* First test with the simpler info2 */
2091 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2093 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2094 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2095 &bufSize);
2096 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2097 if (buf)
2099 ok(bufSize == constraints2[i].encoded[1] + 2,
2100 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2101 bufSize);
2102 ok(!memcmp(buf, constraints2[i].encoded,
2103 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2104 LocalFree(buf);
2107 /* Now test with more complex basic constraints */
2108 info.SubjectType.cbData = 0;
2109 info.fPathLenConstraint = FALSE;
2110 info.cSubtreesConstraint = 0;
2111 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2112 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2113 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2114 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2115 if (buf)
2117 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2118 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2119 "Unexpected value\n");
2120 LocalFree(buf);
2122 /* None of the certs I examined had any subtree constraint, but I test one
2123 * anyway just in case.
2125 info.cSubtreesConstraint = 1;
2126 info.rgSubtreesConstraint = &nameBlob;
2127 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2128 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2129 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2130 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2131 if (buf)
2133 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2134 ok(!memcmp(buf, constraintWithDomainName,
2135 sizeof(constraintWithDomainName)), "Unexpected value\n");
2136 LocalFree(buf);
2138 /* FIXME: test encoding with subject type. */
2141 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2143 static void test_decodeBasicConstraints(DWORD dwEncoding)
2145 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2146 0xff };
2147 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2148 DWORD i;
2149 BOOL ret;
2150 BYTE *buf = NULL;
2151 DWORD bufSize = 0;
2153 /* First test with simpler info2 */
2154 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2156 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2157 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2158 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2159 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2160 GetLastError());
2161 if (buf)
2163 CERT_BASIC_CONSTRAINTS2_INFO *info =
2164 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2166 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2167 "Unexpected value for item %d\n", i);
2168 LocalFree(buf);
2171 /* Check with the order of encoded elements inverted */
2172 buf = (PBYTE)1;
2173 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2174 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2175 &bufSize);
2176 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2177 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2178 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2179 GetLastError());
2180 ok(!buf, "Expected buf to be set to NULL\n");
2181 /* Check with a non-DER bool */
2182 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2183 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2184 &buf, &bufSize);
2185 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2186 if (buf)
2188 CERT_BASIC_CONSTRAINTS2_INFO *info =
2189 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2191 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2192 LocalFree(buf);
2194 /* Check with a non-basic constraints value */
2195 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196 encodedCommonName, encodedCommonName[1] + 2,
2197 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2198 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2199 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2200 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2201 GetLastError());
2202 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2203 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2204 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2205 &buf, &bufSize);
2206 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207 if (buf)
2209 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2211 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2212 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2213 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2214 LocalFree(buf);
2216 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2217 constraintWithDomainName, sizeof(constraintWithDomainName),
2218 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2219 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2220 if (buf)
2222 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2224 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2225 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2226 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2227 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2229 ok(info->rgSubtreesConstraint[0].cbData ==
2230 sizeof(encodedDomainName), "Wrong size %d\n",
2231 info->rgSubtreesConstraint[0].cbData);
2232 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2233 sizeof(encodedDomainName)), "Unexpected value\n");
2235 LocalFree(buf);
2239 /* These are terrible public keys of course, I'm just testing encoding */
2240 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2241 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2242 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2243 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2244 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2245 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2246 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2249 struct EncodedRSAPubKey
2251 const BYTE *modulus;
2252 size_t modulusLen;
2253 const BYTE *encoded;
2254 size_t decodedModulusLen;
2257 struct EncodedRSAPubKey rsaPubKeys[] = {
2258 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2259 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2260 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2261 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2264 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2266 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2267 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2268 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2269 BOOL ret;
2270 BYTE *buf = NULL;
2271 DWORD bufSize = 0, i;
2273 /* Try with a bogus blob type */
2274 hdr->bType = 2;
2275 hdr->bVersion = CUR_BLOB_VERSION;
2276 hdr->reserved = 0;
2277 hdr->aiKeyAlg = CALG_RSA_KEYX;
2278 rsaPubKey->magic = 0x31415352;
2279 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2280 rsaPubKey->pubexp = 65537;
2281 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2282 sizeof(modulus1));
2284 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2285 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2286 ok(!ret && GetLastError() == E_INVALIDARG,
2287 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2288 /* Now with a bogus reserved field */
2289 hdr->bType = PUBLICKEYBLOB;
2290 hdr->reserved = 1;
2291 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2292 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2293 if (buf)
2295 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2296 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2297 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2298 LocalFree(buf);
2300 /* Now with a bogus blob version */
2301 hdr->reserved = 0;
2302 hdr->bVersion = 0;
2303 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2304 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2305 if (buf)
2307 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2308 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2309 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2310 LocalFree(buf);
2312 /* And with a bogus alg ID */
2313 hdr->bVersion = CUR_BLOB_VERSION;
2314 hdr->aiKeyAlg = CALG_DES;
2315 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2316 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2317 if (buf)
2319 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2320 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2321 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2322 LocalFree(buf);
2324 /* Check a couple of RSA-related OIDs */
2325 hdr->aiKeyAlg = CALG_RSA_KEYX;
2326 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2327 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2328 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2329 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2330 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2331 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2332 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334 /* Finally, all valid */
2335 hdr->aiKeyAlg = CALG_RSA_KEYX;
2336 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2338 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2339 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2340 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2341 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2342 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2343 if (buf)
2345 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2346 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2347 bufSize);
2348 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2349 "Unexpected value\n");
2350 LocalFree(buf);
2355 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2357 DWORD i;
2358 LPBYTE buf = NULL;
2359 DWORD bufSize = 0;
2360 BOOL ret;
2362 /* Try with a bad length */
2363 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2364 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2365 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2366 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2367 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2368 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2369 GetLastError());
2370 /* Try with a couple of RSA-related OIDs */
2371 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2372 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2373 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2374 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2375 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2376 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2377 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2378 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2379 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2380 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2381 /* Now try success cases */
2382 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2384 bufSize = 0;
2385 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2386 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2387 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2389 if (buf)
2391 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2392 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2394 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2395 rsaPubKeys[i].decodedModulusLen,
2396 "Wrong size %d\n", bufSize);
2397 ok(hdr->bType == PUBLICKEYBLOB,
2398 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2399 hdr->bType);
2400 ok(hdr->bVersion == CUR_BLOB_VERSION,
2401 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2402 CUR_BLOB_VERSION, hdr->bVersion);
2403 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2404 hdr->reserved);
2405 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2406 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2407 ok(rsaPubKey->magic == 0x31415352,
2408 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2409 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2410 "Wrong bit len %d\n", rsaPubKey->bitlen);
2411 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2412 rsaPubKey->pubexp);
2413 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2414 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2415 "Unexpected modulus\n");
2416 LocalFree(buf);
2421 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2422 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2423 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2425 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2426 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2427 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2428 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2430 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2432 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2433 CRYPT_SEQUENCE_OF_ANY seq;
2434 DWORD i;
2435 BOOL ret;
2436 BYTE *buf = NULL;
2437 DWORD bufSize = 0;
2439 /* Encode a homogeneous sequence */
2440 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2442 blobs[i].cbData = ints[i].encoded[1] + 2;
2443 blobs[i].pbData = (BYTE *)ints[i].encoded;
2445 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2446 seq.rgValue = blobs;
2448 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2450 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2451 if (buf)
2453 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2454 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2455 LocalFree(buf);
2457 /* Change the type of the first element in the sequence, and give it
2458 * another go
2460 blobs[0].cbData = times[0].encodedTime[1] + 2;
2461 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2462 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2463 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2464 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2465 if (buf)
2467 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2468 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2469 "Unexpected value\n");
2470 LocalFree(buf);
2474 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2476 BOOL ret;
2477 BYTE *buf = NULL;
2478 DWORD bufSize = 0;
2480 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2481 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2482 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2483 if (buf)
2485 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2486 DWORD i;
2488 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2489 "Wrong elements %d\n", seq->cValue);
2490 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2492 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2493 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2494 seq->rgValue[i].cbData);
2495 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2496 ints[i].encoded[1] + 2), "Unexpected value\n");
2498 LocalFree(buf);
2500 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2501 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2502 &bufSize);
2503 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2504 if (buf)
2506 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2508 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2509 "Wrong elements %d\n", seq->cValue);
2510 /* Just check the first element since it's all that changed */
2511 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2512 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2513 seq->rgValue[0].cbData);
2514 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2515 times[0].encodedTime[1] + 2), "Unexpected value\n");
2516 LocalFree(buf);
2520 struct encodedExtensions
2522 CERT_EXTENSIONS exts;
2523 const BYTE *encoded;
2526 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2527 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2528 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2529 static CERT_EXTENSION criticalExt =
2530 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2531 static CERT_EXTENSION nonCriticalExt =
2532 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2533 static CHAR oid_short[] = "1.1";
2534 static CERT_EXTENSION extWithShortOid =
2535 { oid_short, FALSE, { 0, NULL } };
2537 static const BYTE ext0[] = { 0x30,0x00 };
2538 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2539 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2540 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2541 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2544 static const struct encodedExtensions exts[] = {
2545 { { 0, NULL }, ext0 },
2546 { { 1, &criticalExt }, ext1 },
2547 { { 1, &nonCriticalExt }, ext2 },
2548 { { 1, &extWithShortOid }, ext3 }
2551 static void test_encodeExtensions(DWORD dwEncoding)
2553 DWORD i;
2555 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2557 BOOL ret;
2558 BYTE *buf = NULL;
2559 DWORD bufSize = 0;
2561 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2562 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2563 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2564 if (buf)
2566 ok(bufSize == exts[i].encoded[1] + 2,
2567 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2568 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2569 "Unexpected value\n");
2570 LocalFree(buf);
2575 static void test_decodeExtensions(DWORD dwEncoding)
2577 DWORD i;
2579 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2581 BOOL ret;
2582 BYTE *buf = NULL;
2583 DWORD bufSize = 0;
2585 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2586 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2587 NULL, &buf, &bufSize);
2588 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2589 if (buf)
2591 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2592 DWORD j;
2594 ok(ext->cExtension == exts[i].exts.cExtension,
2595 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2596 ext->cExtension);
2597 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2599 ok(!strcmp(ext->rgExtension[j].pszObjId,
2600 exts[i].exts.rgExtension[j].pszObjId),
2601 "Expected OID %s, got %s\n",
2602 exts[i].exts.rgExtension[j].pszObjId,
2603 ext->rgExtension[j].pszObjId);
2604 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2605 exts[i].exts.rgExtension[j].Value.pbData,
2606 exts[i].exts.rgExtension[j].Value.cbData),
2607 "Unexpected value\n");
2609 LocalFree(buf);
2614 /* MS encodes public key info with a NULL if the algorithm identifier's
2615 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2616 * it encodes them by omitting the algorithm parameters. This latter approach
2617 * seems more correct, so accept either form.
2619 struct encodedPublicKey
2621 CERT_PUBLIC_KEY_INFO info;
2622 const BYTE *encoded;
2623 const BYTE *encodedNoNull;
2624 CERT_PUBLIC_KEY_INFO decoded;
2627 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2628 0xe, 0xf };
2629 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2631 static const unsigned char bin64[] = {
2632 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2633 static const unsigned char bin65[] = {
2634 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2635 static const unsigned char bin66[] = {
2636 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2637 static const unsigned char bin67[] = {
2638 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2639 static const unsigned char bin68[] = {
2640 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2641 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2642 static const unsigned char bin69[] = {
2643 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2644 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2645 static const unsigned char bin70[] = {
2646 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2647 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2648 0x0f};
2649 static const unsigned char bin71[] = {
2650 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2651 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2652 0x0f};
2653 static unsigned char bin72[] = { 0x05,0x00};
2655 static CHAR oid_bogus[] = "1.2.3",
2656 oid_rsa[] = szOID_RSA;
2658 static const struct encodedPublicKey pubKeys[] = {
2659 /* with a bogus OID */
2660 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2661 bin64, bin65,
2662 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2663 /* some normal keys */
2664 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2665 bin66, bin67,
2666 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2667 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2668 bin68, bin69,
2669 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2670 /* with add'l parameters--note they must be DER-encoded */
2671 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2672 (BYTE *)aKey, 0 } },
2673 bin70, bin71,
2674 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2675 (BYTE *)aKey, 0 } } },
2678 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2680 DWORD i;
2682 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2684 BOOL ret;
2685 BYTE *buf = NULL;
2686 DWORD bufSize = 0;
2688 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2689 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2690 &bufSize);
2691 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2692 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2693 if (buf)
2695 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2696 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2697 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2698 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2699 if (bufSize == pubKeys[i].encoded[1] + 2)
2700 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2701 "Unexpected value\n");
2702 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2703 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2704 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2705 LocalFree(buf);
2710 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2711 const CERT_PUBLIC_KEY_INFO *got)
2713 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2714 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2715 got->Algorithm.pszObjId);
2716 ok(expected->Algorithm.Parameters.cbData ==
2717 got->Algorithm.Parameters.cbData,
2718 "Expected parameters of %d bytes, got %d\n",
2719 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2720 if (expected->Algorithm.Parameters.cbData)
2721 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2722 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2723 "Unexpected algorithm parameters\n");
2724 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2725 "Expected public key of %d bytes, got %d\n",
2726 expected->PublicKey.cbData, got->PublicKey.cbData);
2727 if (expected->PublicKey.cbData)
2728 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2729 got->PublicKey.cbData), "Unexpected public key value\n");
2732 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2734 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2735 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2736 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2737 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2738 DWORD i;
2739 BOOL ret;
2740 BYTE *buf = NULL;
2741 DWORD bufSize = 0;
2743 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2745 /* The NULL form decodes to the decoded member */
2746 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2747 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2748 NULL, &buf, &bufSize);
2749 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2750 if (buf)
2752 comparePublicKeyInfo(&pubKeys[i].decoded,
2753 (CERT_PUBLIC_KEY_INFO *)buf);
2754 LocalFree(buf);
2756 /* The non-NULL form decodes to the original */
2757 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2758 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2759 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2760 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2761 if (buf)
2763 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2764 LocalFree(buf);
2767 /* Test with bogus (not valid DER) parameters */
2768 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2769 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2770 NULL, &buf, &bufSize);
2771 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2772 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2773 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2774 GetLastError());
2777 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2778 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2779 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2780 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2781 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2782 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2783 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2784 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2785 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2786 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2787 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2788 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2789 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2790 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2791 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2792 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2793 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2794 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2795 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2796 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2797 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2798 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2799 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2800 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2801 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2802 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2803 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2804 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2805 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2806 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2807 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2808 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2809 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2810 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2811 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2812 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2813 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2814 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2815 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2816 static const BYTE v1CertWithPubKey[] = {
2817 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2818 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2819 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2820 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2821 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2822 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2823 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2824 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2825 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2826 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2827 0x01,0x01 };
2828 static const BYTE v1CertWithPubKeyNoNull[] = {
2829 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2830 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2831 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2832 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2833 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2834 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2835 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2836 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2837 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2838 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2839 static const BYTE v1CertWithSubjectKeyId[] = {
2840 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2841 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2842 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2843 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2844 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2845 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2846 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2847 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2848 0x4c,0x61,0x6e,0x67,0x00 };
2850 static const BYTE serialNum[] = { 0x01 };
2852 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2854 BOOL ret;
2855 BYTE *buf = NULL;
2856 DWORD size = 0;
2857 CERT_INFO info = { 0 };
2858 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2859 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2860 CERT_EXTENSION ext;
2862 if (0)
2864 /* Test with NULL pvStructInfo (crashes on win9x) */
2865 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2866 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2867 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2868 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2870 /* Test with a V1 cert */
2871 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2872 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2873 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2874 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2875 if (buf)
2877 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2878 v1Cert[1] + 2, size);
2879 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2880 LocalFree(buf);
2882 /* Test v2 cert */
2883 info.dwVersion = CERT_V2;
2884 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2885 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2886 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2887 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2888 if (buf)
2890 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2891 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2892 LocalFree(buf);
2894 /* Test v3 cert */
2895 info.dwVersion = CERT_V3;
2896 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2897 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2898 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2899 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2900 if (buf)
2902 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2903 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2904 LocalFree(buf);
2906 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2907 * API doesn't prevent it)
2909 info.dwVersion = CERT_V1;
2910 info.cExtension = 1;
2911 info.rgExtension = &criticalExt;
2912 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2913 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2914 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2915 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2916 if (buf)
2918 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2919 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2920 LocalFree(buf);
2922 /* test v1 cert with a serial number */
2923 info.SerialNumber.cbData = sizeof(serialNum);
2924 info.SerialNumber.pbData = (BYTE *)serialNum;
2925 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2926 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2927 if (buf)
2929 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2930 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2931 LocalFree(buf);
2933 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2934 info.Issuer.cbData = sizeof(encodedCommonName);
2935 info.Issuer.pbData = (BYTE *)encodedCommonName;
2936 info.Subject.cbData = sizeof(encodedCommonName);
2937 info.Subject.pbData = (BYTE *)encodedCommonName;
2938 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2939 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2940 if (buf)
2942 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2943 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2944 LocalFree(buf);
2946 /* Add a public key */
2947 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2948 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2949 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2950 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2951 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2952 if (buf)
2954 ok(size == sizeof(v1CertWithPubKey) ||
2955 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2956 if (size == sizeof(v1CertWithPubKey))
2957 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2958 else if (size == sizeof(v1CertWithPubKeyNoNull))
2959 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2960 "Got unexpected value\n");
2961 LocalFree(buf);
2963 /* Remove the public key, and add a subject key identifier extension */
2964 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2965 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2966 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2967 ext.pszObjId = oid_subject_key_identifier;
2968 ext.fCritical = FALSE;
2969 ext.Value.cbData = sizeof(octetCommonNameValue);
2970 ext.Value.pbData = octetCommonNameValue;
2971 info.cExtension = 1;
2972 info.rgExtension = &ext;
2973 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2974 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2975 if (buf)
2977 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2978 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2979 LocalFree(buf);
2983 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2985 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2986 v1CertWithConstraints, v1CertWithSerial };
2987 BOOL ret;
2988 BYTE *buf = NULL;
2989 DWORD size = 0, i;
2991 /* Test with NULL pbEncoded */
2992 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2993 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2994 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2995 GetLastError() == OSS_BAD_ARG /* Win9x */),
2996 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2997 if (0)
2999 /* Crashes on win9x */
3000 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3001 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3002 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3003 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3005 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3006 * minimum a cert must have a non-zero serial number, an issuer, and a
3007 * subject.
3009 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3011 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3012 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3013 &buf, &size);
3014 ok(!ret, "Expected failure\n");
3016 /* Now check with serial number, subject and issuer specified */
3017 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3018 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3019 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3020 if (buf)
3022 CERT_INFO *info = (CERT_INFO *)buf;
3024 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3025 ok(info->SerialNumber.cbData == 1,
3026 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3027 ok(*info->SerialNumber.pbData == *serialNum,
3028 "Expected serial number %d, got %d\n", *serialNum,
3029 *info->SerialNumber.pbData);
3030 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3031 "Wrong size %d\n", info->Issuer.cbData);
3032 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3033 "Unexpected issuer\n");
3034 ok(info->Subject.cbData == sizeof(encodedCommonName),
3035 "Wrong size %d\n", info->Subject.cbData);
3036 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3037 info->Subject.cbData), "Unexpected subject\n");
3038 LocalFree(buf);
3040 /* Check again with pub key specified */
3041 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3042 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3043 &buf, &size);
3044 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3045 if (buf)
3047 CERT_INFO *info = (CERT_INFO *)buf;
3049 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3050 ok(info->SerialNumber.cbData == 1,
3051 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3052 ok(*info->SerialNumber.pbData == *serialNum,
3053 "Expected serial number %d, got %d\n", *serialNum,
3054 *info->SerialNumber.pbData);
3055 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3056 "Wrong size %d\n", info->Issuer.cbData);
3057 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3058 "Unexpected issuer\n");
3059 ok(info->Subject.cbData == sizeof(encodedCommonName),
3060 "Wrong size %d\n", info->Subject.cbData);
3061 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3062 info->Subject.cbData), "Unexpected subject\n");
3063 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3064 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3065 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3066 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3067 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3068 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3069 sizeof(aKey)), "Unexpected public key\n");
3070 LocalFree(buf);
3074 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3075 0xe, 0xf };
3077 static const BYTE signedBigCert[] = {
3078 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3079 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3080 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3081 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3082 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3083 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3084 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3085 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3086 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3087 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3088 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3089 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3091 static void test_encodeCert(DWORD dwEncoding)
3093 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3094 * also that bigCert is a NULL-terminated string, so don't count its
3095 * last byte (otherwise the signed cert won't decode.)
3097 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3098 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3099 BOOL ret;
3100 BYTE *buf = NULL;
3101 DWORD bufSize = 0;
3103 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3104 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3105 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3106 if (buf)
3108 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3109 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3110 LocalFree(buf);
3114 static void test_decodeCert(DWORD dwEncoding)
3116 BOOL ret;
3117 BYTE *buf = NULL;
3118 DWORD size = 0;
3120 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3121 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3122 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3123 if (buf)
3125 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3127 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3128 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3129 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3130 "Unexpected cert\n");
3131 ok(info->Signature.cbData == sizeof(hash),
3132 "Wrong signature size %d\n", info->Signature.cbData);
3133 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3134 "Unexpected signature\n");
3135 LocalFree(buf);
3137 /* A signed cert decodes as a CERT_INFO too */
3138 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3139 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3140 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3141 if (buf)
3143 CERT_INFO *info = (CERT_INFO *)buf;
3145 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3146 ok(info->SerialNumber.cbData == 1,
3147 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3148 ok(*info->SerialNumber.pbData == *serialNum,
3149 "Expected serial number %d, got %d\n", *serialNum,
3150 *info->SerialNumber.pbData);
3151 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3152 "Wrong size %d\n", info->Issuer.cbData);
3153 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3154 "Unexpected issuer\n");
3155 ok(info->Subject.cbData == sizeof(encodedCommonName),
3156 "Wrong size %d\n", info->Subject.cbData);
3157 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3158 info->Subject.cbData), "Unexpected subject\n");
3159 LocalFree(buf);
3163 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3164 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3165 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3166 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3167 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3168 0x00, 0x03 };
3169 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3170 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3171 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3172 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3173 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3174 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3175 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3176 0x2e, 0x6f, 0x72, 0x67 };
3177 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3178 CRL_REASON_AFFILIATION_CHANGED;
3180 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3182 CRL_DIST_POINTS_INFO info = { 0 };
3183 CRL_DIST_POINT point = { { 0 } };
3184 CERT_ALT_NAME_ENTRY entry = { 0 };
3185 BOOL ret;
3186 BYTE *buf = NULL;
3187 DWORD size = 0;
3189 /* Test with an empty info */
3190 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3191 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3192 ok(!ret && GetLastError() == E_INVALIDARG,
3193 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3194 /* Test with one empty dist point */
3195 info.cDistPoint = 1;
3196 info.rgDistPoint = &point;
3197 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3198 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3199 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3200 if (buf)
3202 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3203 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3204 LocalFree(buf);
3206 /* A dist point with an invalid name */
3207 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3208 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3209 U(entry).pwszURL = (LPWSTR)nihongoURL;
3210 U(point.DistPointName).FullName.cAltEntry = 1;
3211 U(point.DistPointName).FullName.rgAltEntry = &entry;
3212 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3213 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3214 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3215 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3216 /* The first invalid character is at index 7 */
3217 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3218 "Expected invalid char at index 7, got %d\n",
3219 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3220 /* A dist point with (just) a valid name */
3221 U(entry).pwszURL = (LPWSTR)url;
3222 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3223 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3224 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3225 if (buf)
3227 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3228 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3229 LocalFree(buf);
3231 /* A dist point with (just) reason flags */
3232 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3233 point.ReasonFlags.cbData = sizeof(crlReason);
3234 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3235 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3236 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3237 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3238 if (buf)
3240 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3241 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3242 LocalFree(buf);
3244 /* A dist point with just an issuer */
3245 point.ReasonFlags.cbData = 0;
3246 point.CRLIssuer.cAltEntry = 1;
3247 point.CRLIssuer.rgAltEntry = &entry;
3248 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3249 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3250 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3251 if (buf)
3253 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3254 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3255 LocalFree(buf);
3257 /* A dist point with both a name and an issuer */
3258 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3259 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3260 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3261 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3262 if (buf)
3264 ok(size == sizeof(distPointWithUrlAndIssuer),
3265 "Wrong size %d\n", size);
3266 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3267 LocalFree(buf);
3271 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3273 BOOL ret;
3274 BYTE *buf = NULL;
3275 DWORD size = 0;
3276 PCRL_DIST_POINTS_INFO info;
3277 PCRL_DIST_POINT point;
3278 PCERT_ALT_NAME_ENTRY entry;
3280 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3281 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3282 &buf, &size);
3283 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3284 if (ret)
3286 info = (PCRL_DIST_POINTS_INFO)buf;
3287 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3288 "Wrong size %d\n", size);
3289 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3290 info->cDistPoint);
3291 point = info->rgDistPoint;
3292 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3293 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3294 point->DistPointName.dwDistPointNameChoice);
3295 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3296 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3297 LocalFree(buf);
3299 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3300 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3301 &buf, &size);
3302 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3303 if (ret)
3305 info = (PCRL_DIST_POINTS_INFO)buf;
3306 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3307 "Wrong size %d\n", size);
3308 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3309 info->cDistPoint);
3310 point = info->rgDistPoint;
3311 ok(point->DistPointName.dwDistPointNameChoice ==
3312 CRL_DIST_POINT_FULL_NAME,
3313 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3314 point->DistPointName.dwDistPointNameChoice);
3315 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3316 "Expected 1 name entry, got %d\n",
3317 U(point->DistPointName).FullName.cAltEntry);
3318 entry = U(point->DistPointName).FullName.rgAltEntry;
3319 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3320 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3321 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3322 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3323 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3324 LocalFree(buf);
3326 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3327 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3328 NULL, &buf, &size);
3329 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3330 if (ret)
3332 info = (PCRL_DIST_POINTS_INFO)buf;
3333 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3334 "Wrong size %d\n", size);
3335 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3336 info->cDistPoint);
3337 point = info->rgDistPoint;
3338 ok(point->DistPointName.dwDistPointNameChoice ==
3339 CRL_DIST_POINT_NO_NAME,
3340 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3341 point->DistPointName.dwDistPointNameChoice);
3342 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3343 "Expected reason length\n");
3344 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3345 "Unexpected reason\n");
3346 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3347 LocalFree(buf);
3349 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3350 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3351 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3352 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3353 if (ret)
3355 info = (PCRL_DIST_POINTS_INFO)buf;
3356 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3357 "Wrong size %d\n", size);
3358 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3359 info->cDistPoint);
3360 point = info->rgDistPoint;
3361 ok(point->DistPointName.dwDistPointNameChoice ==
3362 CRL_DIST_POINT_FULL_NAME,
3363 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3364 point->DistPointName.dwDistPointNameChoice);
3365 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3366 "Expected 1 name entry, got %d\n",
3367 U(point->DistPointName).FullName.cAltEntry);
3368 entry = U(point->DistPointName).FullName.rgAltEntry;
3369 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3370 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3371 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3372 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3373 ok(point->CRLIssuer.cAltEntry == 1,
3374 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3375 entry = point->CRLIssuer.rgAltEntry;
3376 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3377 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3378 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3379 LocalFree(buf);
3383 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3384 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3385 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3386 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3387 0x67 };
3389 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3391 BOOL ret;
3392 BYTE *buf = NULL;
3393 DWORD size = 0;
3394 CRL_ISSUING_DIST_POINT point = { { 0 } };
3395 CERT_ALT_NAME_ENTRY entry;
3397 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3398 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3399 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3401 skip("no X509_ISSUING_DIST_POINT encode support\n");
3402 return;
3404 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3405 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3406 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3407 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3408 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3409 if (buf)
3411 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3412 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3413 LocalFree(buf);
3415 /* nonsensical flags */
3416 point.fOnlyContainsUserCerts = TRUE;
3417 point.fOnlyContainsCACerts = TRUE;
3418 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3419 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3420 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3421 if (buf)
3423 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3424 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3425 LocalFree(buf);
3427 /* unimplemented name type */
3428 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3429 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3430 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3431 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3432 ok(!ret && GetLastError() == E_INVALIDARG,
3433 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3434 /* empty name */
3435 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3436 U(point.DistPointName).FullName.cAltEntry = 0;
3437 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3438 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3439 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3440 if (buf)
3442 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3443 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3444 LocalFree(buf);
3446 /* name with URL entry */
3447 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3448 U(entry).pwszURL = (LPWSTR)url;
3449 U(point.DistPointName).FullName.cAltEntry = 1;
3450 U(point.DistPointName).FullName.rgAltEntry = &entry;
3451 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3452 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3453 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3454 if (buf)
3456 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3457 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3458 LocalFree(buf);
3462 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3463 const CERT_ALT_NAME_ENTRY *got)
3465 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3466 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3467 got->dwAltNameChoice);
3468 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3470 switch (got->dwAltNameChoice)
3472 case CERT_ALT_NAME_RFC822_NAME:
3473 case CERT_ALT_NAME_DNS_NAME:
3474 case CERT_ALT_NAME_EDI_PARTY_NAME:
3475 case CERT_ALT_NAME_URL:
3476 case CERT_ALT_NAME_REGISTERED_ID:
3477 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3478 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3479 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3480 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3481 "Unexpected name\n");
3482 break;
3483 case CERT_ALT_NAME_X400_ADDRESS:
3484 case CERT_ALT_NAME_DIRECTORY_NAME:
3485 case CERT_ALT_NAME_IP_ADDRESS:
3486 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3487 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3488 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3489 U(*got).IPAddress.cbData), "Unexpected value\n");
3490 break;
3495 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3496 const CERT_ALT_NAME_INFO *got)
3498 DWORD i;
3500 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3501 expected->cAltEntry, got->cAltEntry);
3502 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3503 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3506 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3507 const CRL_DIST_POINT_NAME *got)
3509 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3510 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3511 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3512 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3515 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3516 const CRL_ISSUING_DIST_POINT *got)
3518 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3519 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3520 "Unexpected fOnlyContainsUserCerts\n");
3521 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3522 "Unexpected fOnlyContainsCACerts\n");
3523 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3524 "Unexpected reason flags\n");
3525 ok(got->fIndirectCRL == expected->fIndirectCRL,
3526 "Unexpected fIndirectCRL\n");
3529 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3531 BOOL ret;
3532 BYTE *buf = NULL;
3533 DWORD size = 0;
3534 CRL_ISSUING_DIST_POINT point = { { 0 } };
3536 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3537 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3538 &buf, &size);
3539 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3541 skip("no X509_ISSUING_DIST_POINT decode support\n");
3542 return;
3544 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3545 if (ret)
3547 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3548 LocalFree(buf);
3550 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3551 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3552 &buf, &size);
3553 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3554 if (ret)
3556 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3557 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3558 LocalFree(buf);
3560 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3561 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3562 &buf, &size);
3563 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3564 if (ret)
3566 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3567 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3568 U(point.DistPointName).FullName.cAltEntry = 0;
3569 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3570 LocalFree(buf);
3572 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3573 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3574 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3575 if (ret)
3577 CERT_ALT_NAME_ENTRY entry;
3579 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3580 U(entry).pwszURL = (LPWSTR)url;
3581 U(point.DistPointName).FullName.cAltEntry = 1;
3582 U(point.DistPointName).FullName.rgAltEntry = &entry;
3583 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3584 LocalFree(buf);
3588 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3589 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3590 0x30, 0x5a };
3591 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3592 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3593 0x30, 0x30, 0x30, 0x30, 0x5a };
3594 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3595 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3596 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3597 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3598 0x5a };
3599 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3600 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3601 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3602 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3603 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3604 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3605 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3606 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3607 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3608 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3609 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3610 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3611 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3612 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3613 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3614 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3615 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3616 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3617 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3618 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3619 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3620 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3621 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3622 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3623 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3624 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3625 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3626 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3627 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3628 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3629 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3630 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3631 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3632 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3633 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3634 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3635 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3636 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3637 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3638 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3640 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3642 BOOL ret;
3643 BYTE *buf = NULL;
3644 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3645 DWORD size = 0;
3646 CRL_INFO info = { 0 };
3647 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3648 CERT_EXTENSION ext;
3650 /* Test with a V1 CRL */
3651 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3652 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3653 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3654 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3655 if (buf)
3657 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3658 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3659 LocalFree(buf);
3661 /* Test v2 CRL */
3662 info.dwVersion = CRL_V2;
3663 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3664 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3665 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3666 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3667 if (buf)
3669 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3670 v2CRL[1] + 2, size);
3671 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3672 LocalFree(buf);
3674 /* v1 CRL with a name */
3675 info.dwVersion = CRL_V1;
3676 info.Issuer.cbData = sizeof(encodedCommonName);
3677 info.Issuer.pbData = (BYTE *)encodedCommonName;
3678 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3679 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3680 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3681 if (buf)
3683 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3684 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3685 LocalFree(buf);
3687 if (0)
3689 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3690 info.cCRLEntry = 1;
3691 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3692 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3693 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3694 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3696 /* now set an empty entry */
3697 info.cCRLEntry = 1;
3698 info.rgCRLEntry = &entry;
3699 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3700 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3701 if (buf)
3703 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3704 "Wrong size %d\n", size);
3705 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3706 "Got unexpected value\n");
3707 LocalFree(buf);
3709 /* an entry with a serial number */
3710 entry.SerialNumber.cbData = sizeof(serialNum);
3711 entry.SerialNumber.pbData = (BYTE *)serialNum;
3712 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3713 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3714 if (buf)
3716 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3717 "Wrong size %d\n", size);
3718 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3719 "Got unexpected value\n");
3720 LocalFree(buf);
3722 /* an entry with an extension */
3723 entry.cExtension = 1;
3724 entry.rgExtension = &criticalExt;
3725 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3726 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3727 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3728 if (buf)
3730 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3731 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3732 LocalFree(buf);
3734 /* a CRL with an extension */
3735 entry.cExtension = 0;
3736 info.cExtension = 1;
3737 info.rgExtension = &criticalExt;
3738 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3739 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3740 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3741 if (buf)
3743 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3744 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3745 LocalFree(buf);
3747 /* a v2 CRL with an extension, this time non-critical */
3748 info.dwVersion = CRL_V2;
3749 info.rgExtension = &nonCriticalExt;
3750 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3751 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3752 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3753 if (buf)
3755 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3756 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3757 LocalFree(buf);
3759 /* a v2 CRL with an issuing dist point extension */
3760 ext.pszObjId = oid_issuing_dist_point;
3761 ext.fCritical = TRUE;
3762 ext.Value.cbData = sizeof(urlIDP);
3763 ext.Value.pbData = (LPBYTE)urlIDP;
3764 entry.rgExtension = &ext;
3765 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3766 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3767 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3768 if (buf)
3770 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3771 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3772 LocalFree(buf);
3776 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3777 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3778 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3779 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3780 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3781 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3782 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3783 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3784 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3785 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3786 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3787 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3788 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3789 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3790 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3791 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3792 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3793 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3794 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3795 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3796 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3797 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3798 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3799 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3800 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3801 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3802 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3803 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3804 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3805 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3806 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3807 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3808 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3809 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3810 0xcd };
3811 static const BYTE verisignCRLWithLotsOfEntries[] = {
3812 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3813 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3814 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3815 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3816 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3817 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3818 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3819 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3820 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3821 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3822 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3823 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3824 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3825 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3826 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3827 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3828 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3829 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3830 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3831 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3832 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3833 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3834 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3835 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3836 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3837 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3838 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3839 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3840 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3841 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3842 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3843 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3844 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3845 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3846 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3847 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3848 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3849 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3850 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3851 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3852 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3853 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3854 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3855 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3856 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3857 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3858 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3859 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3860 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3861 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3862 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3863 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3864 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3865 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3866 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3867 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3868 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3869 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3870 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3871 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3872 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3873 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3874 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3875 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3876 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3877 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3878 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3879 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3880 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3881 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3882 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3883 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3884 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3885 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3886 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3887 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3888 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3889 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3890 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3891 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3892 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3893 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3894 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3895 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3896 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3897 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3898 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3899 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3900 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3901 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3902 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3903 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3904 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3905 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3906 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3907 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3908 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3909 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3910 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3911 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3912 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3913 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3914 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3915 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3916 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3917 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3918 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3919 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3920 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3921 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3922 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3923 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3924 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3925 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3926 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3927 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3928 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3929 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3930 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3931 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3932 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3933 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3934 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3935 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3936 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3937 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3938 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3939 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3940 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3941 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3942 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3943 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3944 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3945 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3946 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3947 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3948 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3949 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3950 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3951 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3952 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3953 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3954 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3955 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3956 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3957 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3958 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3959 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3960 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3961 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3962 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3963 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3964 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3965 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3966 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3967 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3968 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3969 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3970 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3971 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3972 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3973 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3974 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3975 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3976 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3977 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3978 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3979 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3980 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3981 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3982 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3983 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3984 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3985 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3986 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3987 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3988 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3989 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3990 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3991 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3992 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3993 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3994 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3995 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3996 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3997 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3998 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3999 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4000 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4001 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4002 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4003 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4004 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4005 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4006 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4007 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4008 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4009 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4010 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4011 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4012 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4013 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4014 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4015 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4016 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4017 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4018 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4019 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4020 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4021 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4022 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4023 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4024 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4025 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4026 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4027 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4028 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4029 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4030 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4031 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4032 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4033 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4034 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4035 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4036 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4037 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4038 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4039 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4040 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4041 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4042 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4043 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4044 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4045 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4046 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4047 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4048 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4049 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4050 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4051 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4052 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4053 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4054 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4055 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4056 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4057 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4058 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4059 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4060 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4061 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4062 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4063 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4064 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4065 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4066 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4067 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4068 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4069 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4070 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4071 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4072 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4073 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4074 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4075 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4076 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4077 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4078 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4079 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4080 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4081 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4082 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4083 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4084 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4085 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4086 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4087 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4088 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4089 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4090 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4091 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4092 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4093 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4094 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4095 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4096 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4097 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4098 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4099 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4100 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4101 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4102 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4103 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4104 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4105 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4106 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4107 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4108 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4109 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4110 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4111 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4112 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4113 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4114 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4115 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4116 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4117 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4118 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4119 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4120 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4121 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4122 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4123 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4124 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4125 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4126 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4127 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4128 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4129 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4130 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4131 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4132 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4133 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4134 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4135 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4136 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4137 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4138 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4139 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4140 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4141 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4142 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4143 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4144 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4145 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4146 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4147 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4148 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4149 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4150 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4151 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4152 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4153 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4154 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4155 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4156 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4157 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4158 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4159 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4160 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4161 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4162 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4163 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4164 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4165 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4166 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4167 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4168 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4169 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4170 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4171 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4172 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4173 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4174 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4175 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4176 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4177 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4178 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4179 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4180 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4181 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4182 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4183 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4184 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4185 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4186 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4187 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4188 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4189 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4190 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4191 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4192 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4193 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4194 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4195 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4196 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4197 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4198 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4199 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4200 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4201 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4202 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4203 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4204 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4205 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4206 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4207 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4208 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4209 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4210 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4211 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4212 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4213 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4214 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4215 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4216 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4217 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4218 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4219 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4220 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4221 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4222 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4223 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4224 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4225 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4226 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4227 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4228 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4229 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4230 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4231 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4232 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4233 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4234 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4235 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4236 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4237 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4238 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4239 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4240 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4241 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4242 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4243 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4244 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4245 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4246 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4247 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4248 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4249 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4250 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4251 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4252 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4253 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4254 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4255 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4256 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4257 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4258 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4259 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4260 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4261 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4262 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4263 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4264 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4265 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4266 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4267 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4268 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4269 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4270 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4271 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4272 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4273 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4274 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4275 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4276 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4277 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4278 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4279 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4280 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4281 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4282 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4283 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4284 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4285 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4286 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4287 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4288 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4289 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4290 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4291 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4292 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4293 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4294 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4295 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4296 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4297 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4298 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4299 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4300 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4301 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4302 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4303 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4304 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4305 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4306 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4307 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4308 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4309 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4310 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4311 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4312 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4313 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4314 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4315 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4316 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4317 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4318 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4319 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4321 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4323 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4324 BOOL ret;
4325 BYTE *buf = NULL;
4326 DWORD size = 0, i;
4328 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4330 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4331 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4332 &buf, &size);
4333 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4334 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4335 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4336 GetLastError());
4338 /* at a minimum, a CRL must contain an issuer: */
4339 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4340 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4341 &buf, &size);
4342 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4343 if (buf)
4345 CRL_INFO *info = (CRL_INFO *)buf;
4347 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4348 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4349 info->cCRLEntry);
4350 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4351 "Wrong issuer size %d\n", info->Issuer.cbData);
4352 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4353 "Unexpected issuer\n");
4354 LocalFree(buf);
4356 /* check decoding with an empty CRL entry */
4357 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4358 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4359 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4360 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4361 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4362 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4363 GetLastError());
4364 /* with a real CRL entry */
4365 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4366 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4367 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4368 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4369 if (buf)
4371 CRL_INFO *info = (CRL_INFO *)buf;
4372 CRL_ENTRY *entry;
4374 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4375 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4376 info->cCRLEntry);
4377 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4378 entry = info->rgCRLEntry;
4379 ok(entry->SerialNumber.cbData == 1,
4380 "Expected serial number size 1, got %d\n",
4381 entry->SerialNumber.cbData);
4382 ok(*entry->SerialNumber.pbData == *serialNum,
4383 "Expected serial number %d, got %d\n", *serialNum,
4384 *entry->SerialNumber.pbData);
4385 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4386 "Wrong issuer size %d\n", info->Issuer.cbData);
4387 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4388 "Unexpected issuer\n");
4389 LocalFree(buf);
4391 /* a real CRL from verisign that has extensions */
4392 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4393 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4394 NULL, &buf, &size);
4395 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4396 if (buf)
4398 CRL_INFO *info = (CRL_INFO *)buf;
4399 CRL_ENTRY *entry;
4401 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4402 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4403 info->cCRLEntry);
4404 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4405 entry = info->rgCRLEntry;
4406 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4407 info->cExtension);
4408 LocalFree(buf);
4410 /* another real CRL from verisign that has lots of entries */
4411 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4412 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4413 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4414 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4415 if (buf)
4417 CRL_INFO *info = (CRL_INFO *)buf;
4419 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4420 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4421 info->cCRLEntry);
4422 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4423 info->cExtension);
4424 LocalFree(buf);
4426 /* and finally, with an extension */
4427 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4428 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4429 NULL, &buf, &size);
4430 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4431 if (buf)
4433 CRL_INFO *info = (CRL_INFO *)buf;
4434 CRL_ENTRY *entry;
4436 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4437 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4438 info->cCRLEntry);
4439 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4440 entry = info->rgCRLEntry;
4441 ok(entry->SerialNumber.cbData == 1,
4442 "Expected serial number size 1, got %d\n",
4443 entry->SerialNumber.cbData);
4444 ok(*entry->SerialNumber.pbData == *serialNum,
4445 "Expected serial number %d, got %d\n", *serialNum,
4446 *entry->SerialNumber.pbData);
4447 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4448 "Wrong issuer size %d\n", info->Issuer.cbData);
4449 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4450 "Unexpected issuer\n");
4451 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4452 info->cExtension);
4453 LocalFree(buf);
4455 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4456 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4457 NULL, &buf, &size);
4458 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4459 if (buf)
4461 CRL_INFO *info = (CRL_INFO *)buf;
4463 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4464 info->cExtension);
4465 LocalFree(buf);
4467 /* And again, with an issuing dist point */
4468 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4469 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4470 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4471 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4472 if (buf)
4474 CRL_INFO *info = (CRL_INFO *)buf;
4476 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4477 info->cExtension);
4478 LocalFree(buf);
4482 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4483 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4484 static const BYTE encodedUsage[] = {
4485 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4486 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4487 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4489 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4491 BOOL ret;
4492 BYTE *buf = NULL;
4493 DWORD size = 0;
4494 CERT_ENHKEY_USAGE usage;
4496 /* Test with empty usage */
4497 usage.cUsageIdentifier = 0;
4498 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4499 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4500 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4501 if (buf)
4503 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4504 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4505 LocalFree(buf);
4507 /* Test with a few usages */
4508 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4509 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4510 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4511 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4512 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4513 if (buf)
4515 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4516 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4517 LocalFree(buf);
4521 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4523 BOOL ret;
4524 LPBYTE buf = NULL;
4525 DWORD size = 0;
4527 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4528 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4529 &buf, &size);
4530 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4531 if (buf)
4533 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4535 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4536 "Wrong size %d\n", size);
4537 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4538 usage->cUsageIdentifier);
4539 LocalFree(buf);
4541 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4542 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4543 &buf, &size);
4544 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4545 if (buf)
4547 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4548 DWORD i;
4550 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4551 "Wrong size %d\n", size);
4552 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4553 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4554 for (i = 0; i < usage->cUsageIdentifier; i++)
4555 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4556 "Expected OID %s, got %s\n", keyUsages[i],
4557 usage->rgpszUsageIdentifier[i]);
4558 LocalFree(buf);
4562 static BYTE keyId[] = { 1,2,3,4 };
4563 static const BYTE authorityKeyIdWithId[] = {
4564 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4565 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4566 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4567 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4568 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4570 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4572 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4573 BOOL ret;
4574 BYTE *buf = NULL;
4575 DWORD size = 0;
4577 /* Test with empty id */
4578 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4579 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4580 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4581 if (buf)
4583 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4584 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4585 LocalFree(buf);
4587 /* With just a key id */
4588 info.KeyId.cbData = sizeof(keyId);
4589 info.KeyId.pbData = keyId;
4590 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4591 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4592 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4593 if (buf)
4595 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4596 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4597 LocalFree(buf);
4599 /* With just an issuer */
4600 info.KeyId.cbData = 0;
4601 info.CertIssuer.cbData = sizeof(encodedCommonName);
4602 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4603 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4604 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4605 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4606 if (buf)
4608 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4609 size);
4610 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4611 LocalFree(buf);
4613 /* With just a serial number */
4614 info.CertIssuer.cbData = 0;
4615 info.CertSerialNumber.cbData = sizeof(serialNum);
4616 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4617 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4618 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4619 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4620 if (buf)
4622 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4623 size);
4624 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4625 LocalFree(buf);
4629 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4631 BOOL ret;
4632 LPBYTE buf = NULL;
4633 DWORD size = 0;
4635 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4636 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4637 &buf, &size);
4638 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4639 if (buf)
4641 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4643 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4644 size);
4645 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4646 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4647 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4648 LocalFree(buf);
4650 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4651 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4652 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4653 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4654 if (buf)
4656 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4658 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4659 size);
4660 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4661 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4662 "Unexpected key id\n");
4663 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4664 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4665 LocalFree(buf);
4667 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4668 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4669 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4670 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4671 if (buf)
4673 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4675 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4676 size);
4677 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4678 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4679 "Unexpected issuer len\n");
4680 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4681 sizeof(encodedCommonName)), "Unexpected issuer\n");
4682 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4683 LocalFree(buf);
4685 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4686 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4687 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4688 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4689 if (buf)
4691 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4693 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4694 size);
4695 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4696 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4697 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4698 "Unexpected serial number len\n");
4699 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4700 "Unexpected serial number\n");
4701 LocalFree(buf);
4705 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4706 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4707 0x6f,0x72,0x67 };
4709 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4711 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4712 CERT_ALT_NAME_ENTRY entry = { 0 };
4713 BOOL ret;
4714 BYTE *buf = NULL;
4715 DWORD size = 0;
4717 /* Test with empty id */
4718 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4719 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4720 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4721 if (buf)
4723 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4724 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4725 LocalFree(buf);
4727 /* With just a key id */
4728 info.KeyId.cbData = sizeof(keyId);
4729 info.KeyId.pbData = keyId;
4730 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4731 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4732 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4733 if (buf)
4735 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4736 size);
4737 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4738 LocalFree(buf);
4740 /* With a bogus issuer name */
4741 info.KeyId.cbData = 0;
4742 info.AuthorityCertIssuer.cAltEntry = 1;
4743 info.AuthorityCertIssuer.rgAltEntry = &entry;
4744 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4745 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4746 ok(!ret && GetLastError() == E_INVALIDARG,
4747 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4748 /* With an issuer name */
4749 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4750 U(entry).pwszURL = (LPWSTR)url;
4751 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4752 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4753 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4754 if (buf)
4756 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4757 size);
4758 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4759 "Unexpected value\n");
4760 LocalFree(buf);
4762 /* With just a serial number */
4763 info.AuthorityCertIssuer.cAltEntry = 0;
4764 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4765 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4766 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4767 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4768 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4769 if (buf)
4771 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4772 size);
4773 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4774 LocalFree(buf);
4778 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4780 BOOL ret;
4781 LPBYTE buf = NULL;
4782 DWORD size = 0;
4784 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4785 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4786 &buf, &size);
4787 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4788 if (buf)
4790 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4792 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4793 size);
4794 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4795 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4796 "Expected no issuer name entries\n");
4797 ok(info->AuthorityCertSerialNumber.cbData == 0,
4798 "Expected no serial number\n");
4799 LocalFree(buf);
4801 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4802 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4803 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4804 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4805 if (buf)
4807 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4809 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4810 size);
4811 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4812 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4813 "Unexpected key id\n");
4814 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4815 "Expected no issuer name entries\n");
4816 ok(info->AuthorityCertSerialNumber.cbData == 0,
4817 "Expected no serial number\n");
4818 LocalFree(buf);
4820 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4821 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4822 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4823 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4824 if (buf)
4826 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4828 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4829 size);
4830 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4831 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4832 "Expected 1 issuer entry, got %d\n",
4833 info->AuthorityCertIssuer.cAltEntry);
4834 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4835 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4836 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4837 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4838 url), "Unexpected URL\n");
4839 ok(info->AuthorityCertSerialNumber.cbData == 0,
4840 "Expected no serial number\n");
4841 LocalFree(buf);
4843 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4844 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4845 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4846 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4847 if (buf)
4849 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4851 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4852 size);
4853 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4854 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4855 "Expected no issuer name entries\n");
4856 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4857 "Unexpected serial number len\n");
4858 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4859 sizeof(serialNum)), "Unexpected serial number\n");
4860 LocalFree(buf);
4864 static const BYTE authorityInfoAccessWithUrl[] = {
4865 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4866 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4867 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4868 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4869 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4870 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4872 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4874 static char oid1[] = "1.2.3";
4875 static char oid2[] = "1.5.6";
4876 BOOL ret;
4877 BYTE *buf = NULL;
4878 DWORD size = 0;
4879 CERT_ACCESS_DESCRIPTION accessDescription[2];
4880 CERT_AUTHORITY_INFO_ACCESS aia;
4882 memset(accessDescription, 0, sizeof(accessDescription));
4883 aia.cAccDescr = 0;
4884 aia.rgAccDescr = NULL;
4885 /* Having no access descriptions is allowed */
4886 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4887 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4888 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4889 if (buf)
4891 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4892 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4893 LocalFree(buf);
4894 buf = NULL;
4896 /* It can't have an empty access method */
4897 aia.cAccDescr = 1;
4898 aia.rgAccDescr = accessDescription;
4899 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4900 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4901 ok(!ret && (GetLastError() == E_INVALIDARG ||
4902 GetLastError() == OSS_LIMITED /* Win9x */),
4903 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4904 /* It can't have an empty location */
4905 accessDescription[0].pszAccessMethod = oid1;
4906 SetLastError(0xdeadbeef);
4907 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4909 ok(!ret && GetLastError() == E_INVALIDARG,
4910 "expected E_INVALIDARG, got %08x\n", GetLastError());
4911 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4912 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4913 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4914 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4915 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4916 if (buf)
4918 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4919 size);
4920 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4921 "unexpected value\n");
4922 LocalFree(buf);
4923 buf = NULL;
4925 accessDescription[1].pszAccessMethod = oid2;
4926 accessDescription[1].AccessLocation.dwAltNameChoice =
4927 CERT_ALT_NAME_IP_ADDRESS;
4928 U(accessDescription[1].AccessLocation).IPAddress.cbData =
4929 sizeof(encodedIPAddr);
4930 U(accessDescription[1].AccessLocation).IPAddress.pbData =
4931 (LPBYTE)encodedIPAddr;
4932 aia.cAccDescr = 2;
4933 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4934 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4935 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4936 if (buf)
4938 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4939 "unexpected size %d\n", size);
4940 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4941 "unexpected value\n");
4942 LocalFree(buf);
4943 buf = NULL;
4947 static void compareAuthorityInfoAccess(LPCSTR header,
4948 const CERT_AUTHORITY_INFO_ACCESS *expected,
4949 const CERT_AUTHORITY_INFO_ACCESS *got)
4951 DWORD i;
4953 ok(expected->cAccDescr == got->cAccDescr,
4954 "%s: expected %d access descriptions, got %d\n", header,
4955 expected->cAccDescr, got->cAccDescr);
4956 for (i = 0; i < expected->cAccDescr; i++)
4958 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4959 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4960 header, i, expected->rgAccDescr[i].pszAccessMethod,
4961 got->rgAccDescr[i].pszAccessMethod);
4962 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4963 &got->rgAccDescr[i].AccessLocation);
4967 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4969 static char oid1[] = "1.2.3";
4970 static char oid2[] = "1.5.6";
4971 BOOL ret;
4972 LPBYTE buf = NULL;
4973 DWORD size = 0;
4975 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4976 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4977 &buf, &size);
4978 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4979 if (buf)
4981 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4983 compareAuthorityInfoAccess("empty AIA", &aia,
4984 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4985 LocalFree(buf);
4986 buf = NULL;
4988 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4989 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4990 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4991 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4992 if (buf)
4994 CERT_ACCESS_DESCRIPTION accessDescription;
4995 CERT_AUTHORITY_INFO_ACCESS aia;
4997 accessDescription.pszAccessMethod = oid1;
4998 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4999 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5000 aia.cAccDescr = 1;
5001 aia.rgAccDescr = &accessDescription;
5002 compareAuthorityInfoAccess("AIA with URL", &aia,
5003 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5004 LocalFree(buf);
5005 buf = NULL;
5007 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5008 authorityInfoAccessWithUrlAndIPAddr,
5009 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5010 NULL, &buf, &size);
5011 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5012 if (buf)
5014 CERT_ACCESS_DESCRIPTION accessDescription[2];
5015 CERT_AUTHORITY_INFO_ACCESS aia;
5017 accessDescription[0].pszAccessMethod = oid1;
5018 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5019 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5020 accessDescription[1].pszAccessMethod = oid2;
5021 accessDescription[1].AccessLocation.dwAltNameChoice =
5022 CERT_ALT_NAME_IP_ADDRESS;
5023 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5024 sizeof(encodedIPAddr);
5025 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5026 (LPBYTE)encodedIPAddr;
5027 aia.cAccDescr = 2;
5028 aia.rgAccDescr = accessDescription;
5029 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5030 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5031 LocalFree(buf);
5032 buf = NULL;
5036 static const BYTE emptyCTL[] = {
5037 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5038 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5039 static const BYTE emptyCTLWithVersion1[] = {
5040 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5041 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5042 static const BYTE ctlWithUsageIdentifier[] = {
5043 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5044 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5045 static const BYTE ctlWithListIdentifier[] = {
5046 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5047 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5048 static const BYTE ctlWithSequenceNumber[] = {
5049 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5050 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5051 static const BYTE ctlWithThisUpdate[] = {
5052 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5053 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5054 static const BYTE ctlWithThisAndNextUpdate[] = {
5055 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5056 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5057 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5058 static const BYTE ctlWithAlgId[] = {
5059 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5060 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5061 static const BYTE ctlWithBogusEntry[] = {
5062 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5063 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5064 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5065 static const BYTE ctlWithOneEntry[] = {
5066 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5067 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5068 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5069 static const BYTE ctlWithTwoEntries[] = {
5070 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5071 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5072 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5073 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5074 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5076 static void test_encodeCTL(DWORD dwEncoding)
5078 static char oid1[] = "1.2.3";
5079 static char oid2[] = "1.5.6";
5080 char *pOid1 = oid1;
5081 BOOL ret;
5082 BYTE *buf = NULL;
5083 DWORD size = 0;
5084 CTL_INFO info;
5085 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5086 CTL_ENTRY ctlEntry[2];
5087 CRYPT_ATTRIBUTE attr1, attr2;
5088 CRYPT_ATTR_BLOB value1, value2;
5090 memset(&info, 0, sizeof(info));
5091 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5092 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5093 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5094 if (buf)
5096 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5097 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5098 LocalFree(buf);
5099 buf = NULL;
5101 info.dwVersion = 1;
5102 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5103 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5104 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5105 if (buf)
5107 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5108 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5109 LocalFree(buf);
5110 buf = NULL;
5112 info.dwVersion = 0;
5113 info.SubjectUsage.cUsageIdentifier = 1;
5114 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5115 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5116 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5117 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5118 if (buf)
5120 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5121 size);
5122 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5123 LocalFree(buf);
5124 buf = NULL;
5126 info.SubjectUsage.cUsageIdentifier = 0;
5127 info.ListIdentifier.cbData = sizeof(serialNum);
5128 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5129 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5130 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5131 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5132 if (buf)
5134 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5135 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5136 LocalFree(buf);
5137 buf = NULL;
5139 info.ListIdentifier.cbData = 0;
5140 info.SequenceNumber.cbData = sizeof(serialNum);
5141 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5142 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5143 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5144 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5145 if (buf)
5147 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5148 size);
5149 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5150 LocalFree(buf);
5151 buf = NULL;
5153 info.SequenceNumber.cbData = 0;
5154 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5155 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5156 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5157 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5158 if (buf)
5160 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5161 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5162 LocalFree(buf);
5163 buf = NULL;
5165 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5166 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5167 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5168 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5169 if (buf)
5171 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5172 size);
5173 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5174 LocalFree(buf);
5175 buf = NULL;
5177 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5178 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5179 info.SubjectAlgorithm.pszObjId = oid2;
5180 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5181 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5182 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5183 if (buf)
5185 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5186 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5187 LocalFree(buf);
5188 buf = NULL;
5190 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5191 * (see tests below) but it'll encode fine.
5193 info.SubjectAlgorithm.pszObjId = NULL;
5194 value1.cbData = sizeof(serialNum);
5195 value1.pbData = (LPBYTE)serialNum;
5196 attr1.pszObjId = oid1;
5197 attr1.cValue = 1;
5198 attr1.rgValue = &value1;
5199 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5200 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5201 ctlEntry[0].cAttribute = 1;
5202 ctlEntry[0].rgAttribute = &attr1;
5203 info.cCTLEntry = 1;
5204 info.rgCTLEntry = ctlEntry;
5205 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5206 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5207 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5208 if (buf)
5210 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5211 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5212 LocalFree(buf);
5213 buf = NULL;
5215 value1.cbData = sizeof(emptySequence);
5216 value1.pbData = (LPBYTE)emptySequence;
5217 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5218 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5219 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5220 if (buf)
5222 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5223 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5224 LocalFree(buf);
5225 buf = NULL;
5227 value2.cbData = sizeof(encodedIPAddr);
5228 value2.pbData = (LPBYTE)encodedIPAddr;
5229 attr2.pszObjId = oid2;
5230 attr2.cValue = 1;
5231 attr2.rgValue = &value2;
5232 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5233 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5234 ctlEntry[1].cAttribute = 1;
5235 ctlEntry[1].rgAttribute = &attr2;
5236 info.cCTLEntry = 2;
5237 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5238 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5239 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5240 if (buf)
5242 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5243 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5244 LocalFree(buf);
5245 buf = NULL;
5249 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5250 const CTL_INFO *got)
5252 DWORD i, j, k;
5254 ok(expected->dwVersion == got->dwVersion,
5255 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5256 got->dwVersion);
5257 ok(expected->SubjectUsage.cUsageIdentifier ==
5258 got->SubjectUsage.cUsageIdentifier,
5259 "%s: expected %d usage identifiers, got %d\n", header,
5260 expected->SubjectUsage.cUsageIdentifier,
5261 got->SubjectUsage.cUsageIdentifier);
5262 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5263 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5264 got->SubjectUsage.rgpszUsageIdentifier[i]),
5265 "%s[%d]: expected %s, got %s\n", header, i,
5266 expected->SubjectUsage.rgpszUsageIdentifier[i],
5267 got->SubjectUsage.rgpszUsageIdentifier[i]);
5268 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5269 "%s: expected list identifier of %d bytes, got %d\n", header,
5270 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5271 if (expected->ListIdentifier.cbData)
5272 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5273 expected->ListIdentifier.cbData),
5274 "%s: unexpected list identifier value\n", header);
5275 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5276 "%s: expected sequence number of %d bytes, got %d\n", header,
5277 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5278 if (expected->SequenceNumber.cbData)
5279 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5280 expected->SequenceNumber.cbData),
5281 "%s: unexpected sequence number value\n", header);
5282 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5283 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5284 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5285 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5286 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5287 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5288 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5289 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5290 if (expected->SubjectAlgorithm.pszObjId &&
5291 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5292 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5293 expected->SubjectAlgorithm.pszObjId);
5294 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5295 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5296 got->SubjectAlgorithm.pszObjId),
5297 "%s: expected subject algorithm %s, got %s\n", header,
5298 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5299 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5300 got->SubjectAlgorithm.Parameters.cbData,
5301 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5302 expected->SubjectAlgorithm.Parameters.cbData,
5303 got->SubjectAlgorithm.Parameters.cbData);
5304 if (expected->SubjectAlgorithm.Parameters.cbData)
5305 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5306 got->SubjectAlgorithm.Parameters.pbData,
5307 expected->SubjectAlgorithm.Parameters.cbData),
5308 "%s: unexpected subject algorithm parameter value\n", header);
5309 ok(expected->cCTLEntry == got->cCTLEntry,
5310 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5311 got->cCTLEntry);
5312 for (i = 0; i < expected->cCTLEntry; i++)
5314 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5315 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5316 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5317 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5318 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5319 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5320 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5321 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5322 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5323 "%s[%d]: unexpected subject identifier value\n",
5324 header, i);
5325 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5327 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5328 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5329 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5330 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5331 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5332 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5334 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5335 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5336 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5337 header, i, j, k,
5338 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5339 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5340 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5341 ok(!memcmp(
5342 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5343 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5344 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5345 "%s[%d][%d][%d]: unexpected value\n",
5346 header, i, j, k);
5350 ok(expected->cExtension == got->cExtension,
5351 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5352 got->cExtension);
5353 for (i = 0; i < expected->cExtension; i++)
5355 ok(!strcmp(expected->rgExtension[i].pszObjId,
5356 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5357 header, i, expected->rgExtension[i].pszObjId,
5358 got->rgExtension[i].pszObjId);
5359 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5360 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5361 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5362 ok(expected->rgExtension[i].Value.cbData ==
5363 got->rgExtension[i].Value.cbData,
5364 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5365 header, i, expected->rgExtension[i].Value.cbData,
5366 got->rgExtension[i].Value.cbData);
5367 if (expected->rgExtension[i].Value.cbData)
5368 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5369 got->rgExtension[i].Value.pbData,
5370 expected->rgExtension[i].Value.cbData),
5371 "%s[%d]: unexpected extension value\n", header, i);
5375 static const BYTE signedCTL[] = {
5376 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5377 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5378 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5379 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5380 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5381 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5382 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5383 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5384 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5385 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5386 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5387 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5388 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5389 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5390 static const BYTE signedCTLWithCTLInnerContent[] = {
5391 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5392 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5393 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5394 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5395 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5396 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5397 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5398 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5399 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5400 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5401 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5402 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5403 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5404 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5405 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5406 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5407 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5408 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5409 0x57,0x6c,0x0b,0x47,0xb8 };
5411 static void test_decodeCTL(DWORD dwEncoding)
5413 static char oid1[] = "1.2.3";
5414 static char oid2[] = "1.5.6";
5415 static BYTE nullData[] = { 5,0 };
5416 char *pOid1 = oid1;
5417 BOOL ret;
5418 BYTE *buf = NULL;
5419 DWORD size = 0;
5420 CTL_INFO info;
5421 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5422 CTL_ENTRY ctlEntry[2];
5423 CRYPT_ATTRIBUTE attr1, attr2;
5424 CRYPT_ATTR_BLOB value1, value2;
5426 memset(&info, 0, sizeof(info));
5427 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5428 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5429 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5430 if (buf)
5432 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5433 LocalFree(buf);
5434 buf = NULL;
5436 info.dwVersion = 1;
5437 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5438 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5439 &size);
5440 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5441 if (buf)
5443 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5444 LocalFree(buf);
5445 buf = NULL;
5447 info.dwVersion = 0;
5448 info.SubjectUsage.cUsageIdentifier = 1;
5449 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5450 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5451 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5452 &buf, &size);
5453 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5454 if (buf)
5456 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5457 LocalFree(buf);
5458 buf = NULL;
5460 info.SubjectUsage.cUsageIdentifier = 0;
5461 info.ListIdentifier.cbData = sizeof(serialNum);
5462 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5463 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5464 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5465 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5466 if (buf)
5468 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5469 LocalFree(buf);
5470 buf = NULL;
5472 info.ListIdentifier.cbData = 0;
5473 info.SequenceNumber.cbData = sizeof(serialNum);
5474 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5475 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5476 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5477 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5478 if (buf)
5480 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5481 LocalFree(buf);
5482 buf = NULL;
5484 info.SequenceNumber.cbData = 0;
5485 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5486 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5487 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5488 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5489 if (buf)
5491 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5492 LocalFree(buf);
5493 buf = NULL;
5495 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5496 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5497 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5498 &buf, &size);
5499 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5500 if (buf)
5502 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5503 LocalFree(buf);
5504 buf = NULL;
5506 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5507 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5508 info.SubjectAlgorithm.pszObjId = oid2;
5509 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5510 info.SubjectAlgorithm.Parameters.pbData = nullData;
5511 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5512 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5513 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5514 if (buf)
5516 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5517 LocalFree(buf);
5518 buf = NULL;
5520 SetLastError(0xdeadbeef);
5521 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5522 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5523 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5524 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5525 GetLastError());
5526 info.SubjectAlgorithm.Parameters.cbData = 0;
5527 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5528 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5529 info.SubjectAlgorithm.pszObjId = oid2;
5530 info.SubjectAlgorithm.pszObjId = NULL;
5531 value1.cbData = sizeof(emptySequence);
5532 value1.pbData = (LPBYTE)emptySequence;
5533 attr1.pszObjId = oid1;
5534 attr1.cValue = 1;
5535 attr1.rgValue = &value1;
5536 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5537 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5538 ctlEntry[0].cAttribute = 1;
5539 ctlEntry[0].rgAttribute = &attr1;
5540 info.cCTLEntry = 1;
5541 info.rgCTLEntry = ctlEntry;
5542 SetLastError(0xdeadbeef);
5543 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5544 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5545 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5546 if (buf)
5548 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5549 LocalFree(buf);
5550 buf = NULL;
5552 value2.cbData = sizeof(encodedIPAddr);
5553 value2.pbData = (LPBYTE)encodedIPAddr;
5554 attr2.pszObjId = oid2;
5555 attr2.cValue = 1;
5556 attr2.rgValue = &value2;
5557 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5558 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5559 ctlEntry[1].cAttribute = 1;
5560 ctlEntry[1].rgAttribute = &attr2;
5561 info.cCTLEntry = 2;
5562 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5563 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5564 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5565 if (buf)
5567 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5568 LocalFree(buf);
5569 buf = NULL;
5571 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5572 SetLastError(0xdeadbeef);
5573 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5574 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5575 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5576 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5577 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5578 GetLastError());
5579 SetLastError(0xdeadbeef);
5580 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5581 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5582 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5583 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5584 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5585 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5586 GetLastError());
5589 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5590 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5591 0x03,0,0,0,0,0,0 };
5592 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5593 0xa0,0x01,0x01 };
5594 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5595 0x03,0x02,0x01,0x01 };
5596 static BYTE bogusDER[] = { 1 };
5598 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5600 BOOL ret;
5601 BYTE *buf = NULL;
5602 DWORD size = 0;
5603 CRYPT_CONTENT_INFO info = { 0 };
5604 char oid1[] = "1.2.3";
5606 if (0)
5608 /* Crashes on win9x */
5609 SetLastError(0xdeadbeef);
5610 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5611 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5612 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5613 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5615 SetLastError(0xdeadbeef);
5616 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5617 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5618 ok(!ret && (GetLastError() == E_INVALIDARG ||
5619 GetLastError() == OSS_LIMITED /* Win9x */),
5620 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5621 info.pszObjId = oid1;
5622 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5623 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5624 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5625 if (buf)
5627 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5628 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5629 LocalFree(buf);
5631 info.Content.pbData = bogusDER;
5632 info.Content.cbData = sizeof(bogusDER);
5633 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5634 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5635 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5636 if (buf)
5638 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5639 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5640 LocalFree(buf);
5642 info.Content.pbData = (BYTE *)ints[0].encoded;
5643 info.Content.cbData = ints[0].encoded[1] + 2;
5644 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5645 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5646 if (buf)
5648 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5649 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5650 LocalFree(buf);
5654 static const BYTE indefiniteSignedPKCSContent[] = {
5655 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5656 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5657 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5658 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5659 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5660 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5661 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5662 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5663 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5664 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5665 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5666 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5667 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5668 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5669 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5670 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5671 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5672 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5673 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5674 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5675 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5676 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5677 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5678 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5679 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5680 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5681 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5682 0x00,0x00,0x00,0x00,0x00,0x00 };
5684 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5686 BOOL ret;
5687 LPBYTE buf = NULL;
5688 DWORD size = 0;
5689 CRYPT_CONTENT_INFO *info;
5691 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5692 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5693 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5694 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5695 if (buf)
5697 info = (CRYPT_CONTENT_INFO *)buf;
5699 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5700 info->pszObjId);
5701 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5702 info->Content.cbData);
5703 LocalFree(buf);
5705 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5706 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5707 0, NULL, NULL, &size);
5708 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5709 SetLastError(0xdeadbeef);
5710 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5711 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5712 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5713 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5714 * I doubt an app depends on that.
5716 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5717 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5718 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5719 GetLastError());
5720 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5721 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5722 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5723 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5724 if (buf)
5726 info = (CRYPT_CONTENT_INFO *)buf;
5728 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5729 info->pszObjId);
5730 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5731 "Unexpected size %d\n", info->Content.cbData);
5732 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5733 info->Content.cbData), "Unexpected value\n");
5734 LocalFree(buf);
5736 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5737 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5738 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5739 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5740 if (buf)
5742 info = (CRYPT_CONTENT_INFO *)buf;
5744 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5745 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5746 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5747 info->Content.cbData);
5748 LocalFree(buf);
5752 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5753 0x00 };
5754 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5755 0x01 };
5756 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5757 0x02,0x01,0x01 };
5759 static void test_encodePKCSAttribute(DWORD dwEncoding)
5761 CRYPT_ATTRIBUTE attr = { 0 };
5762 BOOL ret;
5763 LPBYTE buf = NULL;
5764 DWORD size = 0;
5765 CRYPT_ATTR_BLOB blob;
5766 char oid[] = "1.2.3";
5768 if (0)
5770 /* Crashes on win9x */
5771 SetLastError(0xdeadbeef);
5772 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5773 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5774 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5775 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5777 SetLastError(0xdeadbeef);
5778 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5780 ok(!ret && (GetLastError() == E_INVALIDARG ||
5781 GetLastError() == OSS_LIMITED /* Win9x */),
5782 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5783 attr.pszObjId = oid;
5784 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5785 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5786 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5787 if (buf)
5789 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5790 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5791 LocalFree(buf);
5793 blob.cbData = sizeof(bogusDER);
5794 blob.pbData = bogusDER;
5795 attr.cValue = 1;
5796 attr.rgValue = &blob;
5797 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5798 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5799 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5800 if (buf)
5802 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5803 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5804 LocalFree(buf);
5806 blob.pbData = (BYTE *)ints[0].encoded;
5807 blob.cbData = ints[0].encoded[1] + 2;
5808 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5809 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5810 if (buf)
5812 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5813 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5814 LocalFree(buf);
5818 static void test_decodePKCSAttribute(DWORD dwEncoding)
5820 BOOL ret;
5821 LPBYTE buf = NULL;
5822 DWORD size = 0;
5823 CRYPT_ATTRIBUTE *attr;
5825 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5826 emptyPKCSAttr, sizeof(emptyPKCSAttr),
5827 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5828 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5829 if (buf)
5831 attr = (CRYPT_ATTRIBUTE *)buf;
5833 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5834 attr->pszObjId);
5835 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5836 LocalFree(buf);
5838 SetLastError(0xdeadbeef);
5839 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5840 bogusPKCSAttr, sizeof(bogusPKCSAttr),
5841 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5842 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5843 * I doubt an app depends on that.
5845 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5846 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5847 GetLastError() == OSS_MORE_INPUT /* Win9x */),
5848 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5849 GetLastError());
5850 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5851 intPKCSAttr, sizeof(intPKCSAttr),
5852 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5853 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5854 if (buf)
5856 attr = (CRYPT_ATTRIBUTE *)buf;
5858 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5859 attr->pszObjId);
5860 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5861 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5862 "Unexpected size %d\n", attr->rgValue[0].cbData);
5863 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5864 attr->rgValue[0].cbData), "Unexpected value\n");
5865 LocalFree(buf);
5869 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5870 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5871 0x2a,0x03,0x31,0x00 };
5872 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5873 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5875 static void test_encodePKCSAttributes(DWORD dwEncoding)
5877 CRYPT_ATTRIBUTES attributes = { 0 };
5878 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5879 CRYPT_ATTR_BLOB blob;
5880 BOOL ret;
5881 LPBYTE buf = NULL;
5882 DWORD size = 0;
5883 char oid1[] = "1.2.3", oid2[] = "1.5.6";
5885 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5886 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5887 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5888 if (buf)
5890 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5891 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5892 LocalFree(buf);
5894 attributes.cAttr = 1;
5895 attributes.rgAttr = attr;
5896 SetLastError(0xdeadbeef);
5897 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5898 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5899 ok(!ret && (GetLastError() == E_INVALIDARG ||
5900 GetLastError() == OSS_LIMITED /* Win9x */),
5901 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5902 attr[0].pszObjId = oid1;
5903 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5904 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5905 if (buf)
5907 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5908 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5909 LocalFree(buf);
5911 attr[1].pszObjId = oid2;
5912 attr[1].cValue = 1;
5913 attr[1].rgValue = &blob;
5914 blob.pbData = (BYTE *)ints[0].encoded;
5915 blob.cbData = ints[0].encoded[1] + 2;
5916 attributes.cAttr = 2;
5917 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5918 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5919 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5920 if (buf)
5922 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5923 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5924 LocalFree(buf);
5928 static void test_decodePKCSAttributes(DWORD dwEncoding)
5930 BOOL ret;
5931 LPBYTE buf = NULL;
5932 DWORD size = 0;
5933 CRYPT_ATTRIBUTES *attributes;
5935 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5936 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5937 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5938 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5939 if (buf)
5941 attributes = (CRYPT_ATTRIBUTES *)buf;
5942 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5943 attributes->cAttr);
5944 LocalFree(buf);
5946 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5947 singlePKCSAttributes, sizeof(singlePKCSAttributes),
5948 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5949 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5950 if (buf)
5952 attributes = (CRYPT_ATTRIBUTES *)buf;
5953 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5954 attributes->cAttr);
5955 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5956 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5957 ok(attributes->rgAttr[0].cValue == 0,
5958 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5959 LocalFree(buf);
5961 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5962 doublePKCSAttributes, sizeof(doublePKCSAttributes),
5963 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5964 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5965 if (buf)
5967 attributes = (CRYPT_ATTRIBUTES *)buf;
5968 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5969 attributes->cAttr);
5970 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5971 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5972 ok(attributes->rgAttr[0].cValue == 0,
5973 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5974 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5975 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5976 ok(attributes->rgAttr[1].cValue == 1,
5977 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5978 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5979 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5980 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5981 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5982 LocalFree(buf);
5986 static const BYTE singleCapability[] = {
5987 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5988 static const BYTE twoCapabilities[] = {
5989 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5990 static const BYTE singleCapabilitywithNULL[] = {
5991 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5993 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5995 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5996 BOOL ret;
5997 LPBYTE buf = NULL;
5998 DWORD size = 0;
5999 CRYPT_SMIME_CAPABILITY capability[2];
6000 CRYPT_SMIME_CAPABILITIES capabilities;
6002 /* An empty capabilities is allowed */
6003 capabilities.cCapability = 0;
6004 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6005 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6006 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6007 if (buf)
6009 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6010 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6011 LocalFree(buf);
6013 /* A non-empty capabilities with an empty capability (lacking an OID) is
6014 * not allowed
6016 capability[0].pszObjId = NULL;
6017 capability[0].Parameters.cbData = 0;
6018 capabilities.cCapability = 1;
6019 capabilities.rgCapability = capability;
6020 SetLastError(0xdeadbeef);
6021 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6022 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6023 ok(!ret && (GetLastError() == E_INVALIDARG ||
6024 GetLastError() == OSS_LIMITED /* Win9x */),
6025 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6026 capability[0].pszObjId = oid1;
6027 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6028 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6029 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6030 if (buf)
6032 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6033 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6034 LocalFree(buf);
6036 capability[1].pszObjId = oid2;
6037 capability[1].Parameters.cbData = 0;
6038 capabilities.cCapability = 2;
6039 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6040 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6041 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6042 if (buf)
6044 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6045 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6046 LocalFree(buf);
6050 static void compareSMimeCapabilities(LPCSTR header,
6051 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6053 DWORD i;
6055 ok(got->cCapability == expected->cCapability,
6056 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6057 got->cCapability);
6058 for (i = 0; i < expected->cCapability; i++)
6060 ok(!strcmp(expected->rgCapability[i].pszObjId,
6061 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6062 header, i, expected->rgCapability[i].pszObjId,
6063 got->rgCapability[i].pszObjId);
6064 ok(expected->rgCapability[i].Parameters.cbData ==
6065 got->rgCapability[i].Parameters.cbData,
6066 "%s[%d]: expected %d bytes, got %d\n", header, i,
6067 expected->rgCapability[i].Parameters.cbData,
6068 got->rgCapability[i].Parameters.cbData);
6069 if (expected->rgCapability[i].Parameters.cbData)
6070 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6071 got->rgCapability[i].Parameters.pbData,
6072 expected->rgCapability[i].Parameters.cbData),
6073 "%s[%d]: unexpected value\n", header, i);
6077 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6079 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6080 BOOL ret;
6081 DWORD size = 0;
6082 CRYPT_SMIME_CAPABILITY capability[2];
6083 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6085 SetLastError(0xdeadbeef);
6086 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6087 emptySequence, sizeof(emptySequence),
6088 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6089 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6090 if (ret)
6092 capabilities.cCapability = 0;
6093 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6094 LocalFree(ptr);
6096 SetLastError(0xdeadbeef);
6097 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6098 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6099 &ptr, &size);
6100 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6101 if (ret)
6103 capability[0].pszObjId = oid1;
6104 capability[0].Parameters.cbData = 0;
6105 capabilities.cCapability = 1;
6106 capabilities.rgCapability = capability;
6107 compareSMimeCapabilities("single capability", &capabilities, ptr);
6108 LocalFree(ptr);
6110 SetLastError(0xdeadbeef);
6111 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6112 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6113 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6114 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6115 if (ret)
6117 BYTE NULLparam[] = {0x05, 0x00};
6118 capability[0].pszObjId = oid1;
6119 capability[0].Parameters.cbData = 2;
6120 capability[0].Parameters.pbData = NULLparam;
6121 capabilities.cCapability = 1;
6122 capabilities.rgCapability = capability;
6123 compareSMimeCapabilities("single capability with NULL", &capabilities,
6124 ptr);
6125 LocalFree(ptr);
6127 SetLastError(0xdeadbeef);
6128 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6129 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6130 &ptr, &size);
6131 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6132 if (ret)
6134 capability[0].Parameters.cbData = 0;
6135 capability[1].pszObjId = oid2;
6136 capability[1].Parameters.cbData = 0;
6137 capabilities.cCapability = 2;
6138 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6139 LocalFree(ptr);
6143 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6144 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6145 0x67 };
6146 static const BYTE minimalPKCSSigner[] = {
6147 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6148 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6149 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6150 static const BYTE PKCSSignerWithSerial[] = {
6151 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6152 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6153 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6154 0x00 };
6155 static const BYTE PKCSSignerWithHashAlgo[] = {
6156 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6157 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6158 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6159 0x00,0x04,0x00 };
6160 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6161 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6162 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6163 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6164 0x06,0x05,0x00,0x04,0x00 };
6165 static const BYTE PKCSSignerWithHash[] = {
6166 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6167 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6168 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6169 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6170 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6171 static const BYTE PKCSSignerWithAuthAttr[] = {
6172 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6173 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6174 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6175 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6176 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6177 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6178 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6180 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6182 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6183 BOOL ret;
6184 LPBYTE buf = NULL;
6185 DWORD size = 0;
6186 CMSG_SIGNER_INFO info = { 0 };
6187 char oid_common_name[] = szOID_COMMON_NAME;
6188 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6189 (LPBYTE)encodedCommonName };
6190 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6192 SetLastError(0xdeadbeef);
6193 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6194 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6195 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6197 skip("no PKCS7_SIGNER_INFO encode support\n");
6198 return;
6200 ok(!ret && (GetLastError() == E_INVALIDARG ||
6201 GetLastError() == OSS_LIMITED /* Win9x */),
6202 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6203 /* To be encoded, a signer must have an issuer at least, and the encoding
6204 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6205 * see decoding tests.)
6207 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6208 info.Issuer.pbData = encodedCommonNameNoNull;
6209 SetLastError(0xdeadbeef);
6210 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6211 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6212 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6213 ok(!ret && GetLastError() == E_INVALIDARG,
6214 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6215 else
6217 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6218 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6219 if (buf)
6221 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6222 if (size == sizeof(minimalPKCSSigner))
6223 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6224 else
6225 ok(0, "Unexpected value\n");
6226 LocalFree(buf);
6229 info.SerialNumber.cbData = sizeof(serialNum);
6230 info.SerialNumber.pbData = (BYTE *)serialNum;
6231 SetLastError(0xdeadbeef);
6232 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6233 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6234 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6235 ok(!ret && GetLastError() == E_INVALIDARG,
6236 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6237 else
6239 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6240 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6241 if (buf)
6243 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6244 size);
6245 if (size == sizeof(PKCSSignerWithSerial))
6246 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6247 "Unexpected value\n");
6248 else
6249 ok(0, "Unexpected value\n");
6250 LocalFree(buf);
6253 info.HashAlgorithm.pszObjId = oid1;
6254 SetLastError(0xdeadbeef);
6255 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6256 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6257 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6258 ok(!ret && GetLastError() == E_INVALIDARG,
6259 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6260 else
6262 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6263 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6264 if (buf)
6266 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6267 size);
6268 if (size == sizeof(PKCSSignerWithHashAlgo))
6269 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6270 "Unexpected value\n");
6271 else
6272 ok(0, "Unexpected value\n");
6273 LocalFree(buf);
6276 info.HashEncryptionAlgorithm.pszObjId = oid2;
6277 SetLastError(0xdeadbeef);
6278 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6279 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6280 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6281 ok(!ret && GetLastError() == E_INVALIDARG,
6282 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6283 else
6285 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6286 if (buf)
6288 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6289 "Unexpected size %d\n", size);
6290 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6291 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6292 "Unexpected value\n");
6293 else
6294 ok(0, "Unexpected value\n");
6295 LocalFree(buf);
6298 info.EncryptedHash.cbData = sizeof(hash);
6299 info.EncryptedHash.pbData = (BYTE *)hash;
6300 SetLastError(0xdeadbeef);
6301 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6302 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6303 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6304 ok(!ret && GetLastError() == E_INVALIDARG,
6305 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6306 else
6308 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6309 if (buf)
6311 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6312 size);
6313 if (size == sizeof(PKCSSignerWithHash))
6314 ok(!memcmp(buf, PKCSSignerWithHash, size),
6315 "Unexpected value\n");
6316 else
6317 ok(0, "Unexpected value\n");
6318 LocalFree(buf);
6321 info.AuthAttrs.cAttr = 1;
6322 info.AuthAttrs.rgAttr = &attr;
6323 SetLastError(0xdeadbeef);
6324 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6325 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6326 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6327 ok(!ret && GetLastError() == E_INVALIDARG,
6328 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6329 else
6331 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6332 if (buf)
6334 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6335 size);
6336 if (size == sizeof(PKCSSignerWithAuthAttr))
6337 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6338 "Unexpected value\n");
6339 else
6340 ok(0, "Unexpected value\n");
6341 LocalFree(buf);
6346 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6348 BOOL ret;
6349 LPBYTE buf = NULL;
6350 DWORD size = 0;
6351 CMSG_SIGNER_INFO *info;
6353 /* A PKCS signer can't be decoded without a serial number. */
6354 SetLastError(0xdeadbeef);
6355 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6356 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6357 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6358 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6359 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6360 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6361 GetLastError());
6362 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6363 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6364 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6365 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6366 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6367 if (buf)
6369 info = (CMSG_SIGNER_INFO *)buf;
6370 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6371 info->dwVersion);
6372 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6373 "Unexpected size %d\n", info->Issuer.cbData);
6374 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6375 info->Issuer.cbData), "Unexpected value\n");
6376 ok(info->SerialNumber.cbData == sizeof(serialNum),
6377 "Unexpected size %d\n", info->SerialNumber.cbData);
6378 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6379 "Unexpected value\n");
6380 LocalFree(buf);
6382 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6383 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6384 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6385 if (buf)
6387 info = (CMSG_SIGNER_INFO *)buf;
6388 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6389 info->dwVersion);
6390 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6391 "Unexpected size %d\n", info->Issuer.cbData);
6392 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6393 info->Issuer.cbData), "Unexpected value\n");
6394 ok(info->SerialNumber.cbData == sizeof(serialNum),
6395 "Unexpected size %d\n", info->SerialNumber.cbData);
6396 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6397 "Unexpected value\n");
6398 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6399 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6400 LocalFree(buf);
6402 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6403 PKCSSignerWithHashAndEncryptionAlgo,
6404 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6405 NULL, &buf, &size);
6406 if (buf)
6408 info = (CMSG_SIGNER_INFO *)buf;
6409 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6410 info->dwVersion);
6411 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6412 "Unexpected size %d\n", info->Issuer.cbData);
6413 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6414 info->Issuer.cbData), "Unexpected value\n");
6415 ok(info->SerialNumber.cbData == sizeof(serialNum),
6416 "Unexpected size %d\n", info->SerialNumber.cbData);
6417 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6418 "Unexpected value\n");
6419 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6420 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6421 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6422 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6423 LocalFree(buf);
6425 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6426 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6427 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6428 if (buf)
6430 info = (CMSG_SIGNER_INFO *)buf;
6431 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6432 info->dwVersion);
6433 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6434 "Unexpected size %d\n", info->Issuer.cbData);
6435 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6436 info->Issuer.cbData), "Unexpected value\n");
6437 ok(info->SerialNumber.cbData == sizeof(serialNum),
6438 "Unexpected size %d\n", info->SerialNumber.cbData);
6439 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6440 "Unexpected value\n");
6441 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6442 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6443 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6444 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6445 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6446 info->EncryptedHash.cbData);
6447 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6448 "Unexpected value\n");
6449 LocalFree(buf);
6451 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6452 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6453 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6454 if (buf)
6456 info = (CMSG_SIGNER_INFO *)buf;
6457 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6458 info->AuthAttrs.cAttr);
6459 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6460 "Expected %s, got %s\n", szOID_COMMON_NAME,
6461 info->AuthAttrs.rgAttr[0].pszObjId);
6462 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6463 info->AuthAttrs.rgAttr[0].cValue);
6464 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6465 sizeof(encodedCommonName), "Unexpected size %d\n",
6466 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6467 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6468 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6469 LocalFree(buf);
6473 static const BYTE CMSSignerWithKeyId[] = {
6474 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6475 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6477 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6479 BOOL ret;
6480 LPBYTE buf = NULL;
6481 DWORD size = 0;
6482 CMSG_CMS_SIGNER_INFO info = { 0 };
6483 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6485 SetLastError(0xdeadbeef);
6486 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6487 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6488 ok(!ret, "Expected failure, got %d\n", ret);
6489 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6491 skip("no CMS_SIGNER_INFO encode support\n");
6492 return;
6494 ok(GetLastError() == E_INVALIDARG,
6495 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6496 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6497 SetLastError(0xdeadbeef);
6498 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6499 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6500 ok(!ret, "Expected failure, got %d\n", ret);
6501 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6503 skip("no CMS_SIGNER_INFO encode support\n");
6504 return;
6506 ok(GetLastError() == E_INVALIDARG,
6507 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6508 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6509 * be a key id or a issuer serial number with at least the issuer set, and
6510 * the encoding must include PKCS_7_ASN_ENCODING.
6511 * (That isn't enough to be decoded, see decoding tests.)
6513 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6514 sizeof(encodedCommonNameNoNull);
6515 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6516 SetLastError(0xdeadbeef);
6517 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6518 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6519 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6520 ok(!ret && GetLastError() == E_INVALIDARG,
6521 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6522 else
6524 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6525 if (buf)
6527 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6528 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6529 LocalFree(buf);
6532 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6533 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6534 SetLastError(0xdeadbeef);
6535 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6536 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6537 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6538 ok(!ret && GetLastError() == E_INVALIDARG,
6539 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6540 else
6542 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6543 if (buf)
6545 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6546 size);
6547 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6548 LocalFree(buf);
6551 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6552 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6553 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6554 SetLastError(0xdeadbeef);
6555 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6556 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6557 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6558 ok(!ret && GetLastError() == E_INVALIDARG,
6559 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6560 else
6562 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6563 if (buf)
6565 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6566 size);
6567 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6568 LocalFree(buf);
6571 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6572 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6573 * (see RFC 3852, section 5.3.)
6575 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6576 U(info.SignerId).HashId.cbData = sizeof(hash);
6577 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6578 SetLastError(0xdeadbeef);
6579 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6580 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6581 ok(!ret && GetLastError() == E_INVALIDARG,
6582 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6583 /* Now with a hash algo */
6584 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6585 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6586 sizeof(encodedCommonNameNoNull);
6587 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6588 info.HashAlgorithm.pszObjId = oid1;
6589 SetLastError(0xdeadbeef);
6590 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6591 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6592 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6593 ok(!ret && GetLastError() == E_INVALIDARG,
6594 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6595 else
6597 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6598 if (buf)
6600 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6601 size);
6602 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6603 "Unexpected value\n");
6604 LocalFree(buf);
6607 info.HashEncryptionAlgorithm.pszObjId = oid2;
6608 SetLastError(0xdeadbeef);
6609 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6610 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6611 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6612 ok(!ret && GetLastError() == E_INVALIDARG,
6613 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6614 else
6616 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6617 if (buf)
6619 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6620 "Unexpected size %d\n", size);
6621 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6622 "Unexpected value\n");
6623 LocalFree(buf);
6626 info.EncryptedHash.cbData = sizeof(hash);
6627 info.EncryptedHash.pbData = (BYTE *)hash;
6628 SetLastError(0xdeadbeef);
6629 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6630 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6631 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6632 ok(!ret && GetLastError() == E_INVALIDARG,
6633 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6634 else
6636 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6637 if (buf)
6639 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6640 size);
6641 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6642 LocalFree(buf);
6647 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6649 BOOL ret;
6650 LPBYTE buf = NULL;
6651 DWORD size = 0;
6652 CMSG_CMS_SIGNER_INFO *info;
6653 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6655 /* A CMS signer can't be decoded without a serial number. */
6656 SetLastError(0xdeadbeef);
6657 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6658 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6659 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6660 ok(!ret, "expected failure\n");
6661 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6663 skip("no CMS_SIGNER_INFO decode support\n");
6664 return;
6666 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6667 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6668 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6669 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6670 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6671 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6672 if (buf)
6674 info = (CMSG_CMS_SIGNER_INFO *)buf;
6675 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6676 info->dwVersion);
6677 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6678 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6679 info->SignerId.dwIdChoice);
6680 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6681 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6682 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6683 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6684 encodedCommonNameNoNull,
6685 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6686 "Unexpected value\n");
6687 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6688 sizeof(serialNum), "Unexpected size %d\n",
6689 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6690 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6691 serialNum, sizeof(serialNum)), "Unexpected value\n");
6692 LocalFree(buf);
6694 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6695 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6696 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6697 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6698 if (buf)
6700 info = (CMSG_CMS_SIGNER_INFO *)buf;
6701 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6702 info->dwVersion);
6703 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6704 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6705 info->SignerId.dwIdChoice);
6706 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6707 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6708 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6709 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6710 encodedCommonNameNoNull,
6711 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6712 "Unexpected value\n");
6713 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6714 sizeof(serialNum), "Unexpected size %d\n",
6715 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6716 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6717 serialNum, sizeof(serialNum)), "Unexpected value\n");
6718 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6719 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6720 LocalFree(buf);
6722 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6723 PKCSSignerWithHashAndEncryptionAlgo,
6724 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6725 NULL, &buf, &size);
6726 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6727 if (buf)
6729 info = (CMSG_CMS_SIGNER_INFO *)buf;
6730 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6731 info->dwVersion);
6732 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6733 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6734 info->SignerId.dwIdChoice);
6735 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6736 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6737 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6738 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6739 encodedCommonNameNoNull,
6740 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6741 "Unexpected value\n");
6742 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6743 sizeof(serialNum), "Unexpected size %d\n",
6744 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6745 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6746 serialNum, sizeof(serialNum)), "Unexpected value\n");
6747 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6748 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6749 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6750 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6751 LocalFree(buf);
6753 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6754 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6755 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6756 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6757 if (buf)
6759 info = (CMSG_CMS_SIGNER_INFO *)buf;
6760 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6761 info->dwVersion);
6762 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6763 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6764 info->SignerId.dwIdChoice);
6765 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6766 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6767 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6768 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6769 encodedCommonNameNoNull,
6770 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6771 "Unexpected value\n");
6772 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6773 sizeof(serialNum), "Unexpected size %d\n",
6774 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6775 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6776 serialNum, sizeof(serialNum)), "Unexpected value\n");
6777 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6778 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6779 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6780 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6781 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6782 info->EncryptedHash.cbData);
6783 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6784 "Unexpected value\n");
6785 LocalFree(buf);
6787 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6788 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6789 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6790 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6791 if (buf)
6793 info = (CMSG_CMS_SIGNER_INFO *)buf;
6794 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6795 info->dwVersion);
6796 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6797 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6798 info->SignerId.dwIdChoice);
6799 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6800 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6801 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6802 "Unexpected value\n");
6803 LocalFree(buf);
6807 static BYTE emptyDNSPermittedConstraints[] = {
6808 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6809 static BYTE emptyDNSExcludedConstraints[] = {
6810 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6811 static BYTE DNSExcludedConstraints[] = {
6812 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6813 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6814 static BYTE permittedAndExcludedConstraints[] = {
6815 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6816 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6817 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6818 static BYTE permittedAndExcludedWithMinConstraints[] = {
6819 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6820 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6821 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6822 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6823 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6824 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6825 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6827 static void test_encodeNameConstraints(DWORD dwEncoding)
6829 BOOL ret;
6830 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6831 CERT_GENERAL_SUBTREE permitted = { { 0 } };
6832 CERT_GENERAL_SUBTREE excluded = { { 0 } };
6833 LPBYTE buf;
6834 DWORD size;
6836 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6837 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6838 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6840 skip("no X509_NAME_CONSTRAINTS encode support\n");
6841 return;
6843 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6844 if (ret)
6846 ok(size == sizeof(emptySequence), "Unexpected size\n");
6847 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6848 LocalFree(buf);
6850 constraints.cPermittedSubtree = 1;
6851 constraints.rgPermittedSubtree = &permitted;
6852 SetLastError(0xdeadbeef);
6853 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6854 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6855 ok(!ret && GetLastError() == E_INVALIDARG,
6856 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6857 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6858 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6859 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6860 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6861 if (ret)
6863 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6864 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6865 "Unexpected value\n");
6866 LocalFree(buf);
6868 constraints.cPermittedSubtree = 0;
6869 constraints.cExcludedSubtree = 1;
6870 constraints.rgExcludedSubtree = &excluded;
6871 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6872 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6873 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6874 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6875 if (ret)
6877 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6878 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6879 "Unexpected value\n");
6880 LocalFree(buf);
6882 U(excluded.Base).pwszURL = (LPWSTR)url;
6883 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6884 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6885 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6886 if (ret)
6888 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6889 ok(!memcmp(buf, DNSExcludedConstraints, size),
6890 "Unexpected value\n");
6891 LocalFree(buf);
6893 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6894 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6895 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6896 constraints.cPermittedSubtree = 1;
6897 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6898 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6899 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6900 if (ret)
6902 ok(size == sizeof(permittedAndExcludedConstraints),
6903 "Unexpected size\n");
6904 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6905 "Unexpected value\n");
6906 LocalFree(buf);
6908 permitted.dwMinimum = 5;
6909 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6910 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6911 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6912 if (ret)
6914 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6915 "Unexpected size\n");
6916 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6917 "Unexpected value\n");
6918 LocalFree(buf);
6920 permitted.fMaximum = TRUE;
6921 permitted.dwMaximum = 3;
6922 SetLastError(0xdeadbeef);
6923 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6924 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6925 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6926 if (ret)
6928 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6929 "Unexpected size\n");
6930 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6931 "Unexpected value\n");
6932 LocalFree(buf);
6936 struct EncodedNameConstraints
6938 CRYPT_DATA_BLOB encoded;
6939 CERT_NAME_CONSTRAINTS_INFO constraints;
6942 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6943 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6944 static CERT_GENERAL_SUBTREE DNSSubtree = {
6945 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6946 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6947 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6948 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6949 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6950 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6951 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6953 struct EncodedNameConstraints encodedNameConstraints[] = {
6954 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6955 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6956 { 1, &emptyDNSSubtree, 0, NULL } },
6957 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6958 { 0, NULL, 1, &emptyDNSSubtree } },
6959 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6960 { 0, NULL, 1, &DNSSubtree } },
6961 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6962 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6963 { { sizeof(permittedAndExcludedWithMinConstraints),
6964 permittedAndExcludedWithMinConstraints },
6965 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6966 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6967 permittedAndExcludedWithMinMaxConstraints },
6968 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6971 static void test_decodeNameConstraints(DWORD dwEncoding)
6973 BOOL ret;
6974 DWORD i;
6975 CERT_NAME_CONSTRAINTS_INFO *constraints;
6977 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6978 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6979 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6980 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6981 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6982 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6983 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6984 for (i = 0;
6985 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6986 i++)
6988 DWORD size;
6990 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6991 encodedNameConstraints[i].encoded.pbData,
6992 encodedNameConstraints[i].encoded.cbData,
6993 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6994 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6996 skip("no X509_NAME_CONSTRAINTS decode support\n");
6997 return;
6999 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7000 if (ret)
7002 DWORD j;
7004 if (constraints->cPermittedSubtree !=
7005 encodedNameConstraints[i].constraints.cPermittedSubtree)
7006 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7007 encodedNameConstraints[i].constraints.cPermittedSubtree,
7008 constraints->cPermittedSubtree);
7009 if (constraints->cPermittedSubtree ==
7010 encodedNameConstraints[i].constraints.cPermittedSubtree)
7012 for (j = 0; j < constraints->cPermittedSubtree; j++)
7014 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7015 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7018 if (constraints->cExcludedSubtree !=
7019 encodedNameConstraints[i].constraints.cExcludedSubtree)
7020 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7021 encodedNameConstraints[i].constraints.cExcludedSubtree,
7022 constraints->cExcludedSubtree);
7023 if (constraints->cExcludedSubtree ==
7024 encodedNameConstraints[i].constraints.cExcludedSubtree)
7026 for (j = 0; j < constraints->cExcludedSubtree; j++)
7028 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7029 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7032 LocalFree(constraints);
7037 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7038 'n','o','t','i','c','e',0 };
7039 static const BYTE noticeWithDisplayText[] = {
7040 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7041 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7042 0x00,0x69,0x00,0x63,0x00,0x65
7044 static char org[] = "Wine";
7045 static int noticeNumbers[] = { 2,3 };
7046 static BYTE noticeWithReference[] = {
7047 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7048 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7049 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7050 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7053 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7055 BOOL ret;
7056 LPBYTE buf;
7057 DWORD size;
7058 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7059 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7061 memset(&notice, 0, sizeof(notice));
7062 ret = pCryptEncodeObjectEx(dwEncoding,
7063 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7064 NULL, &buf, &size);
7065 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7067 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7068 return;
7070 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7071 if (ret)
7073 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7074 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7075 LocalFree(buf);
7077 notice.pszDisplayText = noticeText;
7078 ret = pCryptEncodeObjectEx(dwEncoding,
7079 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7080 NULL, &buf, &size);
7081 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7082 if (ret)
7084 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7085 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7086 LocalFree(buf);
7088 reference.pszOrganization = org;
7089 reference.cNoticeNumbers = 2;
7090 reference.rgNoticeNumbers = noticeNumbers;
7091 notice.pNoticeReference = &reference;
7092 ret = pCryptEncodeObjectEx(dwEncoding,
7093 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7094 NULL, &buf, &size);
7095 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7096 if (ret)
7098 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7099 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7100 LocalFree(buf);
7104 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7106 BOOL ret;
7107 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7108 DWORD size;
7110 ret = pCryptDecodeObjectEx(dwEncoding,
7111 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7112 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7113 &notice, &size);
7114 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7116 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7117 return;
7119 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7120 if (ret)
7122 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7123 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7124 LocalFree(notice);
7126 ret = pCryptDecodeObjectEx(dwEncoding,
7127 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7128 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7129 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7130 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7131 if (ret)
7133 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7134 "unexpected display text\n");
7135 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7136 LocalFree(notice);
7138 ret = pCryptDecodeObjectEx(dwEncoding,
7139 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7140 noticeWithReference, sizeof(noticeWithReference),
7141 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7142 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7143 if (ret)
7145 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7146 "unexpected display text\n");
7147 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7148 if (notice->pNoticeReference)
7150 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7151 "unexpected organization %s\n",
7152 notice->pNoticeReference->pszOrganization);
7153 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7154 "expected 2 notice numbers, got %d\n",
7155 notice->pNoticeReference->cNoticeNumbers);
7156 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7157 "unexpected notice number %d\n",
7158 notice->pNoticeReference->rgNoticeNumbers[0]);
7159 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7160 "unexpected notice number %d\n",
7161 notice->pNoticeReference->rgNoticeNumbers[1]);
7163 LocalFree(notice);
7167 static char oid_any_policy[] = "2.5.29.32.0";
7168 static const BYTE policiesWithAnyPolicy[] = {
7169 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7171 static char oid1[] = "1.2.3";
7172 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7173 static const BYTE twoPolicies[] = {
7174 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7175 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7176 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7177 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7178 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7179 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7182 static void test_encodeCertPolicies(DWORD dwEncoding)
7184 BOOL ret;
7185 CERT_POLICIES_INFO info;
7186 CERT_POLICY_INFO policy[2];
7187 CERT_POLICY_QUALIFIER_INFO qualifier;
7188 LPBYTE buf;
7189 DWORD size;
7191 memset(&info, 0, sizeof(info));
7192 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7193 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7194 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7195 if (ret)
7197 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7198 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7199 LocalFree(buf);
7201 memset(policy, 0, sizeof(policy));
7202 info.cPolicyInfo = 1;
7203 info.rgPolicyInfo = policy;
7204 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7205 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7206 ok(!ret && (GetLastError() == E_INVALIDARG ||
7207 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7208 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7209 policy[0].pszPolicyIdentifier = oid_any_policy;
7210 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7211 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7212 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7213 if (ret)
7215 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7216 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7217 LocalFree(buf);
7219 policy[1].pszPolicyIdentifier = oid1;
7220 memset(&qualifier, 0, sizeof(qualifier));
7221 qualifier.pszPolicyQualifierId = oid_user_notice;
7222 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7223 qualifier.Qualifier.pbData = noticeWithReference;
7224 policy[1].cPolicyQualifier = 1;
7225 policy[1].rgPolicyQualifier = &qualifier;
7226 info.cPolicyInfo = 2;
7227 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7228 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7229 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7230 if (ret)
7232 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7233 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7234 LocalFree(buf);
7238 static void test_decodeCertPolicies(DWORD dwEncoding)
7240 BOOL ret;
7241 CERT_POLICIES_INFO *info;
7242 DWORD size;
7244 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7245 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7246 &info, &size);
7247 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7248 if (ret)
7250 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7251 info->cPolicyInfo);
7252 LocalFree(info);
7254 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7255 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7256 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7257 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7258 if (ret)
7260 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7261 info->cPolicyInfo);
7262 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7263 "unexpected policy id %s\n",
7264 info->rgPolicyInfo[0].pszPolicyIdentifier);
7265 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7266 "unexpected policy qualifier count %d\n",
7267 info->rgPolicyInfo[0].cPolicyQualifier);
7268 LocalFree(info);
7270 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7271 twoPolicies, sizeof(twoPolicies),
7272 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7273 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7274 if (ret)
7276 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7277 info->cPolicyInfo);
7278 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7279 "unexpected policy id %s\n",
7280 info->rgPolicyInfo[0].pszPolicyIdentifier);
7281 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7282 "unexpected policy qualifier count %d\n",
7283 info->rgPolicyInfo[0].cPolicyQualifier);
7284 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7285 "unexpected policy id %s\n",
7286 info->rgPolicyInfo[1].pszPolicyIdentifier);
7287 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7288 "unexpected policy qualifier count %d\n",
7289 info->rgPolicyInfo[1].cPolicyQualifier);
7290 ok(!strcmp(
7291 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7292 oid_user_notice), "unexpected policy qualifier id %s\n",
7293 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7294 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7295 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7296 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7297 ok(!memcmp(
7298 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7299 noticeWithReference, sizeof(noticeWithReference)),
7300 "unexpected qualifier value\n");
7301 LocalFree(info);
7305 /* Free *pInfo with HeapFree */
7306 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7308 BOOL ret;
7309 DWORD size = 0;
7310 HCRYPTKEY key;
7312 /* This crashes
7313 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7315 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7316 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7317 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7318 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7319 &size);
7320 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7321 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7322 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7323 NULL, &size);
7324 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7325 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7326 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7327 0, NULL, NULL, &size);
7328 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7329 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7330 /* Test with no key */
7331 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7332 0, NULL, NULL, &size);
7333 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7334 GetLastError());
7335 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7336 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7337 if (ret)
7339 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7340 NULL, 0, NULL, NULL, &size);
7341 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7342 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7343 if (*pInfo)
7345 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7346 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7347 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7348 GetLastError());
7349 if (ret)
7351 /* By default (we passed NULL as the OID) the OID is
7352 * szOID_RSA_RSA.
7354 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7355 "Expected %s, got %s\n", szOID_RSA_RSA,
7356 (*pInfo)->Algorithm.pszObjId);
7360 CryptDestroyKey(key);
7363 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7364 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7365 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7366 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7367 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7368 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7369 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7370 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7371 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7372 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7373 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7374 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7375 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7376 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7377 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7378 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7379 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7380 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7381 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7382 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7383 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7384 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7385 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7386 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7387 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7389 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7391 BOOL ret;
7392 HCRYPTKEY key;
7393 PCCERT_CONTEXT context;
7394 DWORD dwSize;
7395 ALG_ID ai;
7397 /* These crash
7398 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7399 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7400 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7401 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7402 NULL);
7404 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7405 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7406 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7407 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7408 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7409 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7410 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7411 &key);
7412 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7413 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7415 /* Export key with standard algorithm (CALG_RSA_KEYX) */
7416 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7417 &key);
7418 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7420 dwSize = sizeof(ai);
7421 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7422 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7423 if(ret)
7425 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7426 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7429 CryptDestroyKey(key);
7431 /* Repeat with forced algorithm */
7432 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7433 &key);
7434 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7436 dwSize = sizeof(ai);
7437 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7438 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7439 if(ret)
7441 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7442 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7445 CryptDestroyKey(key);
7447 /* Test importing a public key from a certificate context */
7448 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7449 sizeof(expiredCert));
7450 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7451 GetLastError());
7452 if (context)
7454 ok(!strcmp(szOID_RSA_RSA,
7455 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7456 "Expected %s, got %s\n", szOID_RSA_RSA,
7457 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7458 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7459 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7460 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7461 CryptDestroyKey(key);
7462 CertFreeCertificateContext(context);
7466 static const char cspName[] = "WineCryptTemp";
7468 static void testPortPublicKeyInfo(void)
7470 HCRYPTPROV csp;
7471 BOOL ret;
7472 PCERT_PUBLIC_KEY_INFO info = NULL;
7474 /* Just in case a previous run failed, delete this thing */
7475 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7476 CRYPT_DELETEKEYSET);
7477 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7478 CRYPT_NEWKEYSET);
7480 testExportPublicKey(csp, &info);
7481 testImportPublicKey(csp, info);
7483 HeapFree(GetProcessHeap(), 0, info);
7484 CryptReleaseContext(csp, 0);
7485 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7486 CRYPT_DELETEKEYSET);
7489 START_TEST(encode)
7491 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7492 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7493 HMODULE hCrypt32;
7494 DWORD i;
7496 hCrypt32 = GetModuleHandleA("crypt32.dll");
7497 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7498 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7499 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7501 win_skip("CryptDecodeObjectEx() is not available\n");
7502 return;
7505 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7507 test_encodeInt(encodings[i]);
7508 test_decodeInt(encodings[i]);
7509 test_encodeEnumerated(encodings[i]);
7510 test_decodeEnumerated(encodings[i]);
7511 test_encodeFiletime(encodings[i]);
7512 test_decodeFiletime(encodings[i]);
7513 test_encodeName(encodings[i]);
7514 test_decodeName(encodings[i]);
7515 test_encodeUnicodeName(encodings[i]);
7516 test_decodeUnicodeName(encodings[i]);
7517 test_encodeNameValue(encodings[i]);
7518 test_decodeNameValue(encodings[i]);
7519 test_encodeUnicodeNameValue(encodings[i]);
7520 test_decodeUnicodeNameValue(encodings[i]);
7521 test_encodeAltName(encodings[i]);
7522 test_decodeAltName(encodings[i]);
7523 test_encodeOctets(encodings[i]);
7524 test_decodeOctets(encodings[i]);
7525 test_encodeBits(encodings[i]);
7526 test_decodeBits(encodings[i]);
7527 test_encodeBasicConstraints(encodings[i]);
7528 test_decodeBasicConstraints(encodings[i]);
7529 test_encodeRsaPublicKey(encodings[i]);
7530 test_decodeRsaPublicKey(encodings[i]);
7531 test_encodeSequenceOfAny(encodings[i]);
7532 test_decodeSequenceOfAny(encodings[i]);
7533 test_encodeExtensions(encodings[i]);
7534 test_decodeExtensions(encodings[i]);
7535 test_encodePublicKeyInfo(encodings[i]);
7536 test_decodePublicKeyInfo(encodings[i]);
7537 test_encodeCertToBeSigned(encodings[i]);
7538 test_decodeCertToBeSigned(encodings[i]);
7539 test_encodeCert(encodings[i]);
7540 test_decodeCert(encodings[i]);
7541 test_encodeCRLDistPoints(encodings[i]);
7542 test_decodeCRLDistPoints(encodings[i]);
7543 test_encodeCRLIssuingDistPoint(encodings[i]);
7544 test_decodeCRLIssuingDistPoint(encodings[i]);
7545 test_encodeCRLToBeSigned(encodings[i]);
7546 test_decodeCRLToBeSigned(encodings[i]);
7547 test_encodeEnhancedKeyUsage(encodings[i]);
7548 test_decodeEnhancedKeyUsage(encodings[i]);
7549 test_encodeAuthorityKeyId(encodings[i]);
7550 test_decodeAuthorityKeyId(encodings[i]);
7551 test_encodeAuthorityKeyId2(encodings[i]);
7552 test_decodeAuthorityKeyId2(encodings[i]);
7553 test_encodeAuthorityInfoAccess(encodings[i]);
7554 test_decodeAuthorityInfoAccess(encodings[i]);
7555 test_encodeCTL(encodings[i]);
7556 test_decodeCTL(encodings[i]);
7557 test_encodePKCSContentInfo(encodings[i]);
7558 test_decodePKCSContentInfo(encodings[i]);
7559 test_encodePKCSAttribute(encodings[i]);
7560 test_decodePKCSAttribute(encodings[i]);
7561 test_encodePKCSAttributes(encodings[i]);
7562 test_decodePKCSAttributes(encodings[i]);
7563 test_encodePKCSSMimeCapabilities(encodings[i]);
7564 test_decodePKCSSMimeCapabilities(encodings[i]);
7565 test_encodePKCSSignerInfo(encodings[i]);
7566 test_decodePKCSSignerInfo(encodings[i]);
7567 test_encodeCMSSignerInfo(encodings[i]);
7568 test_decodeCMSSignerInfo(encodings[i]);
7569 test_encodeNameConstraints(encodings[i]);
7570 test_decodeNameConstraints(encodings[i]);
7571 test_encodePolicyQualifierUserNotice(encodings[i]);
7572 test_decodePolicyQualifierUserNotice(encodings[i]);
7573 test_encodeCertPolicies(encodings[i]);
7574 test_decodeCertPolicies(encodings[i]);
7576 testPortPublicKeyInfo();