sync crypt32_winetest with wine 1.1.34
[reactos.git] / rostests / winetests / crypt32 / encode.c
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3 *
4 * Copyright 2005 Juan Lang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35 int val;
36 const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48 { 1, bin1 },
49 { 127, bin2 },
50 { 128, bin3 },
51 { 256, bin4 },
52 { -128, bin5 },
53 { -129, bin6 },
54 { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59 const BYTE *val;
60 const BYTE *encoded;
61 const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73 { bin8, bin9, bin10 },
74 { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84 { bin14, bin15, NULL },
85 { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90 DWORD bufSize = 0;
91 int i;
92 BOOL ret;
93 CRYPT_INTEGER_BLOB blob;
94 BYTE *buf = NULL;
95
96 /* CryptEncodeObjectEx with NULL bufSize crashes..
97 ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 NULL);
99 */
100 /* check bogus encoding */
101 ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102 &bufSize);
103 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105 if (0)
106 {
107 /* check with NULL integer buffer. Windows XP incorrectly returns an
108 * NTSTATUS (crashes on win9x).
109 */
110 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111 &bufSize);
112 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114 }
115 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116 {
117 /* encode as normal integer */
118 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119 NULL, NULL, &bufSize);
120 ok(ret, "Expected success, got %d\n", GetLastError());
121 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124 if (buf)
125 {
126 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127 buf[0]);
128 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129 buf[1], ints[i].encoded[1]);
130 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132 LocalFree(buf);
133 }
134 /* encode as multibyte integer */
135 blob.cbData = sizeof(ints[i].val);
136 blob.pbData = (BYTE *)&ints[i].val;
137 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138 0, NULL, NULL, &bufSize);
139 ok(ret, "Expected success, got %d\n", GetLastError());
140 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143 if (buf)
144 {
145 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146 buf[0]);
147 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148 buf[1], ints[i].encoded[1]);
149 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151 LocalFree(buf);
152 }
153 }
154 /* encode a couple bigger ints, just to show it's little-endian and leading
155 * sign bytes are dropped
156 */
157 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158 {
159 blob.cbData = strlen((const char*)bigInts[i].val);
160 blob.pbData = (BYTE *)bigInts[i].val;
161 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162 0, NULL, NULL, &bufSize);
163 ok(ret, "Expected success, got %d\n", GetLastError());
164 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167 if (buf)
168 {
169 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170 buf[0]);
171 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172 buf[1], bigInts[i].encoded[1]);
173 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174 bigInts[i].encoded[1] + 1),
175 "Encoded value didn't match expected\n");
176 LocalFree(buf);
177 }
178 }
179 /* and, encode some uints */
180 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181 {
182 blob.cbData = strlen((const char*)bigUInts[i].val);
183 blob.pbData = (BYTE*)bigUInts[i].val;
184 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185 0, NULL, NULL, &bufSize);
186 ok(ret, "Expected success, got %d\n", GetLastError());
187 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190 if (buf)
191 {
192 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193 buf[0]);
194 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195 buf[1], bigUInts[i].encoded[1]);
196 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197 bigUInts[i].encoded[1] + 1),
198 "Encoded value didn't match expected\n");
199 LocalFree(buf);
200 }
201 }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211 BYTE *buf = NULL;
212 DWORD bufSize = 0;
213 int i;
214 BOOL ret;
215
216 /* CryptDecodeObjectEx with NULL bufSize crashes..
217 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219 */
220 /* check bogus encoding */
221 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* check with NULL integer buffer */
226 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227 &bufSize);
228 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229 GetLastError() == OSS_BAD_ARG /* Win9x */),
230 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231 /* check with a valid, but too large, integer */
232 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233 CRYPT_DECODE_ALLOC_FLAG, NULL, &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++)
245 {
246 /* When the output buffer is NULL, this always succeeds */
247 SetLastError(0xdeadbeef);
248 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250 &bufSize);
251 ok(ret && GetLastError() == NOERROR,
252 "Expected success and NOERROR, got %d\n", GetLastError());
253 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254 ints[i].encoded, ints[i].encoded[1] + 2,
255 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258 ok(buf != NULL, "Expected allocated buffer\n");
259 if (buf)
260 {
261 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262 ints[i].val, *(int *)buf);
263 LocalFree(buf);
264 }
265 }
266 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267 {
268 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270 &bufSize);
271 ok(ret && GetLastError() == NOERROR,
272 "Expected success and NOERROR, got %d\n", GetLastError());
273 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278 ok(buf != NULL, "Expected allocated buffer\n");
279 if (buf)
280 {
281 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285 blob->cbData);
286 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287 "Unexpected value\n");
288 LocalFree(buf);
289 }
290 }
291 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292 {
293 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295 &bufSize);
296 ok(ret && GetLastError() == NOERROR,
297 "Expected success and NOERROR, got %d\n", GetLastError());
298 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303 ok(buf != NULL, "Expected allocated buffer\n");
304 if (buf)
305 {
306 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310 blob->cbData);
311 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312 "Unexpected value\n");
313 LocalFree(buf);
314 }
315 }
316 /* Decode the value 1 with long-form length */
317 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320 if (buf)
321 {
322 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323 LocalFree(buf);
324 }
325 /* check with extra bytes at the end */
326 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329 if (buf)
330 {
331 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332 LocalFree(buf);
333 }
334 /* Try to decode some bogus large items */
335 /* The buffer size is smaller than the encoded length, so this should fail
336 * with CRYPT_E_ASN1_EOD if it's being decoded.
337 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339 * So this test unfortunately isn't useful.
340 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344 */
345 /* This will try to decode the buffer and overflow it, check that it's
346 * caught.
347 */
348 if (0)
349 {
350 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355 }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362 * particular value
363 */
364 static const struct encodedInt enums[] = {
365 { 1, bin18 },
366 { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370 * X509_ENUMERATED.
371 */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373 szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377 DWORD i, j;
378
379 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380 {
381 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382 {
383 BOOL ret;
384 BYTE *buf = NULL;
385 DWORD bufSize = 0;
386
387 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389 &bufSize);
390 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391 if (buf)
392 {
393 ok(buf[0] == 0xa,
394 "Got unexpected type %d for enumerated (expected 0xa)\n",
395 buf[0]);
396 ok(buf[1] == enums[j].encoded[1],
397 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399 enums[j].encoded[1] + 1),
400 "Encoded value of 0x%08x didn't match expected\n",
401 enums[j].val);
402 LocalFree(buf);
403 }
404 }
405 }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410 DWORD i, j;
411
412 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413 {
414 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415 {
416 BOOL ret;
417 DWORD bufSize = sizeof(int);
418 int val;
419
420 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422 &val, &bufSize);
423 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424 ok(bufSize == sizeof(int),
425 "Got unexpected size %d for enumerated\n", bufSize);
426 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427 val, enums[j].val);
428 }
429 }
430 }
431
432 struct encodedFiletime
433 {
434 SYSTEMTIME sysTime;
435 const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439 const struct encodedFiletime *time)
440 {
441 FILETIME ft = { 0 };
442 BYTE *buf = NULL;
443 DWORD bufSize = 0;
444 BOOL ret;
445
446 ret = SystemTimeToFileTime(&time->sysTime, &ft);
447 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450 /* years other than 1950-2050 are not allowed for encodings other than
451 * X509_CHOICE_OF_TIME.
452 */
453 if (structType == X509_CHOICE_OF_TIME ||
454 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455 {
456 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457 GetLastError());
458 ok(buf != NULL, "Expected an allocated buffer\n");
459 if (buf)
460 {
461 ok(buf[0] == time->encodedTime[0],
462 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463 buf[0]);
464 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465 time->encodedTime[1], bufSize);
466 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467 "Got unexpected value for time encoding\n");
468 LocalFree(buf);
469 }
470 }
471 else
472 ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473 broken(GetLastError() == ERROR_SUCCESS),
474 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479 static char buf[25];
480
481 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483 return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488 static char buf[25];
489 SYSTEMTIME st;
490
491 FileTimeToSystemTime(ft, &st);
492 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494 return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499 SYSTEMTIME st;
500
501 FileTimeToSystemTime(got, &st);
502 ok((expected->wYear == st.wYear &&
503 expected->wMonth == st.wMonth &&
504 expected->wDay == st.wDay &&
505 expected->wHour == st.wHour &&
506 expected->wMinute == st.wMinute &&
507 expected->wSecond == st.wSecond &&
508 abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509 /* Some Windows systems only seem to be accurate in their time decoding to
510 * within about an hour.
511 */
512 broken(expected->wYear == st.wYear &&
513 expected->wMonth == st.wMonth &&
514 expected->wDay == st.wDay &&
515 abs(expected->wHour - st.wHour) <= 1),
516 "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517 printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521 const struct encodedFiletime *time)
522 {
523 FILETIME ft = { 0 };
524 DWORD size = sizeof(ft);
525 BOOL ret;
526
527 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528 time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529 /* years other than 1950-2050 are not allowed for encodings other than
530 * X509_CHOICE_OF_TIME.
531 */
532 if (structType == X509_CHOICE_OF_TIME ||
533 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534 {
535 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536 "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537 GetLastError());
538 if (ret)
539 compareTime(&time->sysTime, &ft);
540 }
541 else
542 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545 GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563 DWORD i;
564
565 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566 {
567 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570 }
571 }
572
573 static const BYTE bin23[] = {
574 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598 0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602 0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604 0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608 static const struct encodedFiletime otherTimes[] = {
609 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
610 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
612 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
613 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
614 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
615 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
616 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
617 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
618 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
619 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
620 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
621 };
622 /* An oddball case that succeeds in Windows, but doesn't seem correct
623 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
624 */
625 static const unsigned char *bogusTimes[] = {
626 /* oddly, this succeeds on Windows, with year 2765
627 "\x18" "\x0f" "21r50606161000Z",
628 */
629 bin35,
630 bin36,
631 bin37,
632 bin38,
633 };
634 DWORD i, size;
635 FILETIME ft1 = { 0 }, ft2 = { 0 };
636 BOOL ret;
637
638 /* Check bogus length with non-NULL buffer */
639 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641 size = 1;
642 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644 ok(!ret && GetLastError() == ERROR_MORE_DATA,
645 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646 /* Normal tests */
647 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648 {
649 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652 }
653 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654 {
655 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658 }
659 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660 {
661 size = sizeof(ft1);
662 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665 GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666 broken(ret), /* Win9x and NT4 for bin38 */
667 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668 GetLastError());
669 }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
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,
686 };
687
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 };
701
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 }
704
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) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
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
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
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;
753
754 if (0)
755 {
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());
761 }
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)
769 {
770 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771 "Got unexpected encoding for empty name\n");
772 LocalFree(buf);
773 }
774 if (0)
775 {
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());
782 }
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)
792 {
793 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794 "Got unexpected encoding for empty RDN array\n");
795 LocalFree(buf);
796 }
797 if (0)
798 {
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());
806 }
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");
817 */
818 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
819 * the encoded attributes to be swapped.
820 */
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)
835 {
836 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837 "Got unexpected encoding for two RDN array\n");
838 LocalFree(buf);
839 }
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)
849 {
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);
854 }
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)
873 {
874 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876 LocalFree(buf);
877 }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
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 };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
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;
903
904 if (0)
905 {
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());
911 }
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)
919 {
920 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921 "Got unexpected encoding for empty name\n");
922 LocalFree(buf);
923 }
924 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925 * encoding (the NULL).
926 */
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.
942 */
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)
959 {
960 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961 "Got unexpected encoding for two RDN array\n");
962 LocalFree(buf);
963 }
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)
973 {
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);
978 }
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)
986 {
987 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989 LocalFree(buf);
990 }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994 const CERT_NAME_VALUE *got)
995 {
996 if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997 got->dwValueType == CERT_RDN_ENCODED_BLOB)
998 {
999 win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000 return;
1001 }
1002
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);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016 const CERT_RDN_ATTR *got)
1017 {
1018 if (expected->pszObjId && strlen(expected->pszObjId))
1019 {
1020 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021 expected->pszObjId);
1022 if (got->pszObjId)
1023 {
1024 ok(!strcmp(got->pszObjId, expected->pszObjId),
1025 "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026 expected->pszObjId);
1027 }
1028 }
1029 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030 (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035 ok(got->cRDNAttr == expected->cRDNAttr,
1036 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037 if (got->cRDNAttr)
1038 {
1039 DWORD i;
1040
1041 for (i = 0; i < got->cRDNAttr; i++)
1042 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043 }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047 const CERT_NAME_INFO *got)
1048 {
1049 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050 expected->cRDN, got->cRDN);
1051 if (got->cRDN)
1052 {
1053 DWORD i;
1054
1055 for (i = 0; i < got->cRDN; i++)
1056 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057 }
1058 }
1059
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};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068 BYTE *buf = NULL;
1069 DWORD bufSize = 0;
1070 BOOL ret;
1071 CERT_RDN rdn;
1072 CERT_NAME_INFO info = { 1, &rdn };
1073
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.
1083 */
1084 if (buf)
1085 {
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);
1091 }
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)
1098 {
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);
1104 }
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)
1113 {
1114 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
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);
1120 }
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)
1129 {
1130 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1131 oid_common_name[] = szOID_COMMON_NAME;
1132
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 } },
1138 };
1139
1140 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141 rdn.rgRDNAttr = attrs;
1142 compareNames(&info, (CERT_NAME_INFO *)buf);
1143 LocalFree(buf);
1144 }
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)
1157 {
1158 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159 rdn.rgRDNAttr = decodedRdnAttrs;
1160 compareNames(&info, (CERT_NAME_INFO *)buf);
1161 LocalFree(buf);
1162 }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167 BYTE *buf = NULL;
1168 DWORD bufSize = 0;
1169 BOOL ret;
1170 CERT_RDN rdn;
1171 CERT_NAME_INFO info = { 1, &rdn };
1172
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)
1181 {
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);
1188 }
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)
1197 {
1198 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
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);
1204 }
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)
1213 {
1214 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1215 oid_common_name[] = szOID_COMMON_NAME;
1216
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 } },
1222 };
1223
1224 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225 rdn.rgRDNAttr = attrs;
1226 compareNames(&info, (CERT_NAME_INFO *)buf);
1227 LocalFree(buf);
1228 }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233 CERT_NAME_VALUE value;
1234 const BYTE *encoded;
1235 DWORD encodedSize;
1236 };
1237
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 };
1267 static char embedded_null[] = "foo\0com";
1268 static BYTE ia5EmbeddedNull[] = {
1269 0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1270
1271 static struct EncodedNameValue nameValues[] = {
1272 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273 octetCommonNameValue, sizeof(octetCommonNameValue) },
1274 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275 numericCommonNameValue, sizeof(numericCommonNameValue) },
1276 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277 printableCommonNameValue, sizeof(printableCommonNameValue) },
1278 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279 t61CommonNameValue, sizeof(t61CommonNameValue) },
1280 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1282 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1284 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1286 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1288 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289 generalCommonNameValue, sizeof(generalCommonNameValue) },
1290 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1291 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1292 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1294 /* The following tests succeed under Windows, but really should fail,
1295 * they contain characters that are illegal for the encoding. I'm
1296 * including them to justify my lazy encoding.
1297 */
1298 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1299 sizeof(bin42) },
1300 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1301 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1302 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1303 bin44, sizeof(bin44) },
1304 };
1305 /* This is kept separate, because the decoding doesn't return to the original
1306 * value.
1307 */
1308 static struct EncodedNameValue embeddedNullNameValue = {
1309 { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1310 ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1311
1312 static void test_encodeNameValue(DWORD dwEncoding)
1313 {
1314 BYTE *buf = NULL;
1315 DWORD size = 0, i;
1316 BOOL ret;
1317 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1318
1319 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1320 value.Value.pbData = printableCommonNameValue;
1321 value.Value.cbData = sizeof(printableCommonNameValue);
1322 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1323 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1324 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1325 if (buf)
1326 {
1327 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1328 size);
1329 ok(!memcmp(buf, printableCommonNameValue, size),
1330 "Unexpected encoding\n");
1331 LocalFree(buf);
1332 }
1333 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1334 {
1335 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1336 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1337 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1338 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1339 nameValues[i].value.dwValueType, GetLastError());
1340 if (ret)
1341 {
1342 ok(size == nameValues[i].encodedSize,
1343 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1344 ok(!memcmp(buf, nameValues[i].encoded, size),
1345 "Got unexpected encoding\n");
1346 LocalFree(buf);
1347 }
1348 }
1349 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1350 &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1351 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1352 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1353 embeddedNullNameValue.value.dwValueType, GetLastError());
1354 if (ret)
1355 {
1356 ok(size == embeddedNullNameValue.encodedSize,
1357 "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1358 ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1359 "Got unexpected encoding\n");
1360 LocalFree(buf);
1361 }
1362 }
1363
1364 static void test_decodeNameValue(DWORD dwEncoding)
1365 {
1366 int i;
1367 BYTE *buf = NULL;
1368 DWORD bufSize = 0;
1369 BOOL ret;
1370
1371 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1372 {
1373 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1374 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1375 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1376 &buf, &bufSize);
1377 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1378 nameValues[i].value.dwValueType, GetLastError());
1379 if (ret)
1380 {
1381 compareNameValues(&nameValues[i].value,
1382 (const CERT_NAME_VALUE *)buf);
1383 LocalFree(buf);
1384 }
1385 }
1386 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1387 embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1388 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1389 &buf, &bufSize);
1390 /* Some Windows versions disallow name values with embedded NULLs, so
1391 * either success or failure is acceptable.
1392 */
1393 if (ret)
1394 {
1395 CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1396 { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1397 CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1398 { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1399 const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1400 *expected = NULL;
1401
1402 /* Some Windows versions decode name values with embedded NULLs,
1403 * others leave them encoded, even with the same version of crypt32.
1404 * Accept either.
1405 */
1406 ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1407 got->dwValueType == CERT_RDN_IA5_STRING,
1408 "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1409 got->dwValueType);
1410 if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1411 expected = &rdnEncodedValue;
1412 else if (got->dwValueType == CERT_RDN_IA5_STRING)
1413 expected = &embeddedNullValue;
1414 if (expected)
1415 {
1416 ok(got->Value.cbData == expected->Value.cbData,
1417 "String type %d: unexpected data size, got %d, expected %d\n",
1418 got->dwValueType, got->Value.cbData, expected->Value.cbData);
1419 if (got->Value.cbData && got->Value.pbData)
1420 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1421 min(got->Value.cbData, expected->Value.cbData)),
1422 "String type %d: unexpected value\n", expected->dwValueType);
1423 }
1424 LocalFree(buf);
1425 }
1426 }
1427
1428 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1429 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1430 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1431 'h','q','.','o','r','g',0 };
1432 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1433 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1434 0x6f, 0x72, 0x67 };
1435 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1436 0x575b, 0 };
1437 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1438 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1439 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1440 static const BYTE localhost[] = { 127, 0, 0, 1 };
1441 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1442 0x01 };
1443 static const unsigned char encodedCommonName[] = {
1444 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1445 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1446 static const BYTE encodedDirectoryName[] = {
1447 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1448 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1449
1450 static void test_encodeAltName(DWORD dwEncoding)
1451 {
1452 CERT_ALT_NAME_INFO info = { 0 };
1453 CERT_ALT_NAME_ENTRY entry = { 0 };
1454 BYTE *buf = NULL;
1455 DWORD size = 0;
1456 BOOL ret;
1457 char oid[] = "1.2.3";
1458
1459 /* Test with empty info */
1460 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1461 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1462 if (buf)
1463 {
1464 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1465 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1466 LocalFree(buf);
1467 }
1468 /* Test with an empty entry */
1469 info.cAltEntry = 1;
1470 info.rgAltEntry = &entry;
1471 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1473 ok(!ret && GetLastError() == E_INVALIDARG,
1474 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1475 /* Test with an empty pointer */
1476 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1477 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1478 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1479 if (buf)
1480 {
1481 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1482 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1483 LocalFree(buf);
1484 }
1485 /* Test with a real URL */
1486 U(entry).pwszURL = (LPWSTR)url;
1487 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1488 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1489 if (buf)
1490 {
1491 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1492 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1493 LocalFree(buf);
1494 }
1495 /* Now with the URL containing an invalid IA5 char */
1496 U(entry).pwszURL = (LPWSTR)nihongoURL;
1497 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1498 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1499 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1500 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1501 /* The first invalid character is at index 7 */
1502 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1503 "Expected invalid char at index 7, got %d\n",
1504 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1505 /* Now with the URL missing a scheme */
1506 U(entry).pwszURL = (LPWSTR)dnsName;
1507 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1508 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1509 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1510 if (buf)
1511 {
1512 /* This succeeds, but it shouldn't, so don't worry about conforming */
1513 LocalFree(buf);
1514 }
1515 /* Now with a DNS name */
1516 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1517 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1518 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1519 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1520 if (buf)
1521 {
1522 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1523 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1524 LocalFree(buf);
1525 }
1526 /* Test with an IP address */
1527 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1528 U(entry).IPAddress.cbData = sizeof(localhost);
1529 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1530 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1531 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1532 if (buf)
1533 {
1534 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1535 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1536 LocalFree(buf);
1537 }
1538 /* Test with OID */
1539 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1540 U(entry).pszRegisteredID = oid;
1541 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1542 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1543 if (buf)
1544 {
1545 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1546 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1547 LocalFree(buf);
1548 }
1549 /* Test with directory name */
1550 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1551 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1552 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1553 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1554 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1555 if (buf)
1556 {
1557 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1558 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1559 LocalFree(buf);
1560 }
1561 }
1562
1563 static void test_decodeAltName(DWORD dwEncoding)
1564 {
1565 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1566 0x00, 0x00, 0x01 };
1567 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1568 0x01 };
1569 static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1570 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1571 static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1572 0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1573 static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1574 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1575 BOOL ret;
1576 BYTE *buf = NULL;
1577 DWORD bufSize = 0;
1578 CERT_ALT_NAME_INFO *info;
1579
1580 /* Test some bogus ones first */
1581 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1582 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1583 NULL, &buf, &bufSize);
1584 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1585 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1586 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1587 GetLastError());
1588 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1589 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1590 &bufSize);
1591 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1592 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1593 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1594 GetLastError());
1595 /* Now expected cases */
1596 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1597 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1598 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1599 if (buf)
1600 {
1601 info = (CERT_ALT_NAME_INFO *)buf;
1602
1603 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1604 info->cAltEntry);
1605 LocalFree(buf);
1606 }
1607 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1608 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1609 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1610 if (buf)
1611 {
1612 info = (CERT_ALT_NAME_INFO *)buf;
1613
1614 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1615 info->cAltEntry);
1616 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1617 "Expected CERT_ALT_NAME_URL, got %d\n",
1618 info->rgAltEntry[0].dwAltNameChoice);
1619 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1620 "Expected empty URL\n");
1621 LocalFree(buf);
1622 }
1623 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1624 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1625 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1626 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1627 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1628 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1629 if (buf)
1630 {
1631 info = (CERT_ALT_NAME_INFO *)buf;
1632
1633 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1634 info->cAltEntry);
1635 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1636 "Expected CERT_ALT_NAME_URL, got %d\n",
1637 info->rgAltEntry[0].dwAltNameChoice);
1638 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1639 LocalFree(buf);
1640 }
1641 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1642 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1643 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1644 if (buf)
1645 {
1646 info = (CERT_ALT_NAME_INFO *)buf;
1647
1648 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1649 info->cAltEntry);
1650 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1651 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1652 info->rgAltEntry[0].dwAltNameChoice);
1653 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1654 "Unexpected DNS name\n");
1655 LocalFree(buf);
1656 }
1657 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1658 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1659 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1660 if (buf)
1661 {
1662 info = (CERT_ALT_NAME_INFO *)buf;
1663
1664 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1665 info->cAltEntry);
1666 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1667 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1668 info->rgAltEntry[0].dwAltNameChoice);
1669 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1670 "Unexpected IP address length %d\n",
1671 U(info->rgAltEntry[0]).IPAddress.cbData);
1672 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1673 sizeof(localhost)), "Unexpected IP address value\n");
1674 LocalFree(buf);
1675 }
1676 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1677 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1678 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1679 if (buf)
1680 {
1681 info = (CERT_ALT_NAME_INFO *)buf;
1682
1683 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1684 info->cAltEntry);
1685 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1686 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1687 info->rgAltEntry[0].dwAltNameChoice);
1688 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1689 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1690 LocalFree(buf);
1691 }
1692 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1693 encodedDirectoryName, sizeof(encodedDirectoryName),
1694 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1695 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1696 if (buf)
1697 {
1698 info = (CERT_ALT_NAME_INFO *)buf;
1699
1700 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1701 info->cAltEntry);
1702 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1703 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1704 info->rgAltEntry[0].dwAltNameChoice);
1705 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1706 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1707 U(info->rgAltEntry[0]).DirectoryName.cbData);
1708 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1709 encodedCommonName, sizeof(encodedCommonName)),
1710 "Unexpected directory name value\n");
1711 LocalFree(buf);
1712 }
1713 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1714 dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1715 NULL, &buf, &bufSize);
1716 /* Fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned about the
1717 * particular failure, just that it doesn't decode.
1718 * It succeeds on (broken) Windows versions that haven't addressed
1719 * embedded NULLs in alternate names.
1720 */
1721 ok(!ret || broken(ret), "expected failure\n");
1722 /* An embedded bell character is allowed, however. */
1723 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1724 dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1725 NULL, &buf, &bufSize);
1726 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1727 if (ret)
1728 {
1729 info = (CERT_ALT_NAME_INFO *)buf;
1730
1731 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1732 info->cAltEntry);
1733 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1734 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1735 info->rgAltEntry[0].dwAltNameChoice);
1736 LocalFree(buf);
1737 }
1738 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1739 url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1740 NULL, &buf, &bufSize);
1741 /* Again, fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned
1742 * about the particular failure, just that it doesn't decode.
1743 * It succeeds on (broken) Windows versions that haven't addressed
1744 * embedded NULLs in alternate names.
1745 */
1746 ok(!ret || broken(ret), "expected failure\n");
1747 }
1748
1749 struct UnicodeExpectedError
1750 {
1751 DWORD valueType;
1752 LPCWSTR str;
1753 DWORD errorIndex;
1754 DWORD error;
1755 };
1756
1757 static const WCHAR oneW[] = { '1',0 };
1758 static const WCHAR aW[] = { 'a',0 };
1759 static const WCHAR quoteW[] = { '"', 0 };
1760
1761 static struct UnicodeExpectedError unicodeErrors[] = {
1762 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1763 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1764 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1765 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1766 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1767 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1768 };
1769
1770 struct UnicodeExpectedResult
1771 {
1772 DWORD valueType;
1773 LPCWSTR str;
1774 CRYPT_DATA_BLOB encoded;
1775 };
1776
1777 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1778 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1779 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1780 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1781 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1782 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1783 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1784 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1785 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1786 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1787 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1788 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1789 0x5b };
1790 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1791 0x6f,0x5b };
1792 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1793 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1794 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1795 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1796
1797 static struct UnicodeExpectedResult unicodeResults[] = {
1798 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1799 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1800 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1801 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1802 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1803 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1804 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1805 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1806 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1807 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1808 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1809 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1810 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1811 };
1812
1813 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1814 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1815 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1816 };
1817
1818 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1819 {
1820 BYTE *buf = NULL;
1821 DWORD size = 0, i;
1822 BOOL ret;
1823 CERT_NAME_VALUE value;
1824
1825 if (0)
1826 {
1827 /* Crashes on win9x */
1828 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1829 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1830 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1831 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1832 }
1833 /* Have to have a string of some sort */
1834 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1835 value.Value.pbData = NULL;
1836 value.Value.cbData = 0;
1837 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1838 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1839 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1840 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1841 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1842 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1843 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1844 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1845 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1846 value.dwValueType = CERT_RDN_ANY_TYPE;
1847 value.Value.pbData = (LPBYTE)oneW;
1848 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1849 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1850 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1851 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1852 value.Value.cbData = sizeof(oneW);
1853 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1854 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1855 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1856 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1857 /* An encoded string with specified length isn't good enough either */
1858 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1859 value.Value.pbData = oneUniversal;
1860 value.Value.cbData = sizeof(oneUniversal);
1861 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1862 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1863 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1864 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1865 /* More failure checking */
1866 value.Value.cbData = 0;
1867 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1868 {
1869 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1870 value.dwValueType = unicodeErrors[i].valueType;
1871 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1872 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1873 ok(!ret && GetLastError() == unicodeErrors[i].error,
1874 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1875 unicodeErrors[i].error, GetLastError());
1876 ok(size == unicodeErrors[i].errorIndex,
1877 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1878 size);
1879 }
1880 /* cbData can be zero if the string is NULL-terminated */
1881 value.Value.cbData = 0;
1882 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1883 {
1884 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1885 value.dwValueType = unicodeResults[i].valueType;
1886 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1887 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1888 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1889 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1890 if (buf)
1891 {
1892 ok(size == unicodeResults[i].encoded.cbData,
1893 "Value type %d: expected size %d, got %d\n",
1894 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1895 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1896 "Value type %d: unexpected value\n", value.dwValueType);
1897 LocalFree(buf);
1898 }
1899 }
1900 /* These "encode," but they do so by truncating each unicode character
1901 * rather than properly encoding it. Kept separate from the proper results,
1902 * because the encoded forms won't decode to their original strings.
1903 */
1904 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1905 {
1906 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1907 value.dwValueType = unicodeWeirdness[i].valueType;
1908 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1909 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1910 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1911 if (buf)
1912 {
1913 ok(size == unicodeWeirdness[i].encoded.cbData,
1914 "Value type %d: expected size %d, got %d\n",
1915 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1916 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1917 "Value type %d: unexpected value\n", value.dwValueType);
1918 LocalFree(buf);
1919 }
1920 }
1921 }
1922
1923 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1924 {
1925 if (n <= 0) return 0;
1926 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1927 return *str1 - *str2;
1928 }
1929
1930 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1931 {
1932 DWORD i;
1933
1934 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1935 {
1936 BYTE *buf = NULL;
1937 BOOL ret;
1938 DWORD size = 0;
1939
1940 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1941 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1942 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1943 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1944 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1945 if (ret && buf)
1946 {
1947 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1948
1949 ok(value->dwValueType == unicodeResults[i].valueType,
1950 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1951 value->dwValueType);
1952 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1953 value->Value.cbData / sizeof(WCHAR)),
1954 "Unexpected decoded value for index %d (value type %d)\n", i,
1955 unicodeResults[i].valueType);
1956 LocalFree(buf);
1957 }
1958 }
1959 }
1960
1961 struct encodedOctets
1962 {
1963 const BYTE *val;
1964 const BYTE *encoded;
1965 };
1966
1967 static const unsigned char bin46[] = { 'h','i',0 };
1968 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1969 static const unsigned char bin48[] = {
1970 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1971 static const unsigned char bin49[] = {
1972 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1973 static const unsigned char bin50[] = { 0 };
1974 static const unsigned char bin51[] = { 0x04,0x00,0 };
1975
1976 static const struct encodedOctets octets[] = {
1977 { bin46, bin47 },
1978 { bin48, bin49 },
1979 { bin50, bin51 },
1980 };
1981
1982 static void test_encodeOctets(DWORD dwEncoding)
1983 {
1984 CRYPT_DATA_BLOB blob;
1985 DWORD i;
1986
1987 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1988 {
1989 BYTE *buf = NULL;
1990 BOOL ret;
1991 DWORD bufSize = 0;
1992
1993 blob.cbData = strlen((const char*)octets[i].val);
1994 blob.pbData = (BYTE*)octets[i].val;
1995 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1996 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1997 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1998 if (buf)
1999 {
2000 ok(buf[0] == 4,
2001 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2002 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2003 buf[1], octets[i].encoded[1]);
2004 ok(!memcmp(buf + 1, octets[i].encoded + 1,
2005 octets[i].encoded[1] + 1), "Got unexpected value\n");
2006 LocalFree(buf);
2007 }
2008 }
2009 }
2010
2011 static void test_decodeOctets(DWORD dwEncoding)
2012 {
2013 DWORD i;
2014
2015 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2016 {
2017 BYTE *buf = NULL;
2018 BOOL ret;
2019 DWORD bufSize = 0;
2020
2021 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2022 octets[i].encoded, octets[i].encoded[1] + 2,
2023 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2024 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2025 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2026 "Expected size >= %d, got %d\n",
2027 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2028 ok(buf != NULL, "Expected allocated buffer\n");
2029 if (buf)
2030 {
2031 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2032
2033 if (blob->cbData)
2034 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2035 "Unexpected value\n");
2036 LocalFree(buf);
2037 }
2038 }
2039 }
2040
2041 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2042
2043 struct encodedBits
2044 {
2045 DWORD cUnusedBits;
2046 const BYTE *encoded;
2047 DWORD cbDecoded;
2048 const BYTE *decoded;
2049 };
2050
2051 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2052 static const unsigned char bin53[] = { 0xff,0xff };
2053 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2054 static const unsigned char bin55[] = { 0xff,0xfe };
2055 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2056 static const unsigned char bin57[] = { 0xfe };
2057 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2058
2059 static const struct encodedBits bits[] = {
2060 /* normal test cases */
2061 { 0, bin52, 2, bin53 },
2062 { 1, bin54, 2, bin55 },
2063 /* strange test case, showing cUnusedBits >= 8 is allowed */
2064 { 9, bin56, 1, bin57 },
2065 };
2066
2067 static void test_encodeBits(DWORD dwEncoding)
2068 {
2069 DWORD i;
2070
2071 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2072 {
2073 CRYPT_BIT_BLOB blob;
2074 BOOL ret;
2075 BYTE *buf = NULL;
2076 DWORD bufSize = 0;
2077
2078 blob.cbData = sizeof(bytesToEncode);
2079 blob.pbData = (BYTE *)bytesToEncode;
2080 blob.cUnusedBits = bits[i].cUnusedBits;
2081 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2082 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2083 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2084 if (buf)
2085 {
2086 ok(bufSize == bits[i].encoded[1] + 2,
2087 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2088 bits[i].encoded[1] + 2);
2089 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2090 "%d: Unexpected value\n", i);
2091 LocalFree(buf);
2092 }
2093 }
2094 }
2095
2096 static void test_decodeBits(DWORD dwEncoding)
2097 {
2098 static const BYTE ber[] = "\x03\x02\x01\xff";
2099 static const BYTE berDecoded = 0xfe;
2100 DWORD i;
2101 BOOL ret;
2102 BYTE *buf = NULL;
2103 DWORD bufSize = 0;
2104
2105 /* normal cases */
2106 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2107 {
2108 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2109 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2110 &bufSize);
2111 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2112 if (buf)
2113 {
2114 CRYPT_BIT_BLOB *blob;
2115
2116 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2117 "Got unexpected size %d\n", bufSize);
2118 blob = (CRYPT_BIT_BLOB *)buf;
2119 ok(blob->cbData == bits[i].cbDecoded,
2120 "Got unexpected length %d, expected %d\n", blob->cbData,
2121 bits[i].cbDecoded);
2122 if (blob->cbData && bits[i].cbDecoded)
2123 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2124 "Unexpected value\n");
2125 LocalFree(buf);
2126 }
2127 }
2128 /* special case: check that something that's valid in BER but not in DER
2129 * decodes successfully
2130 */
2131 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2132 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2133 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2134 if (buf)
2135 {
2136 CRYPT_BIT_BLOB *blob;
2137
2138 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2139 "Got unexpected size %d\n", bufSize);
2140 blob = (CRYPT_BIT_BLOB *)buf;
2141 ok(blob->cbData == sizeof(berDecoded),
2142 "Got unexpected length %d\n", blob->cbData);
2143 if (blob->cbData)
2144 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2145 LocalFree(buf);
2146 }
2147 }
2148
2149 struct Constraints2
2150 {
2151 CERT_BASIC_CONSTRAINTS2_INFO info;
2152 const BYTE *encoded;
2153 };
2154
2155 static const unsigned char bin59[] = { 0x30,0x00 };
2156 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2157 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2158 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2159 static const struct Constraints2 constraints2[] = {
2160 /* empty constraints */
2161 { { FALSE, FALSE, 0}, bin59 },
2162 /* can be a CA */
2163 { { TRUE, FALSE, 0}, bin60 },
2164 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2165 * but that's not the case
2166 */
2167 { { FALSE, TRUE, 0}, bin61 },
2168 /* can be a CA and has path length constraints set */
2169 { { TRUE, TRUE, 1}, bin62 },
2170 };
2171
2172 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2173 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2174 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2175 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2176 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2177 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2178 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2179 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2180 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2181 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2182
2183 static void test_encodeBasicConstraints(DWORD dwEncoding)
2184 {
2185 DWORD i, bufSize = 0;
2186 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2187 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2188 (LPBYTE)encodedDomainName };
2189 BOOL ret;
2190 BYTE *buf = NULL;
2191
2192 /* First test with the simpler info2 */
2193 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2194 {
2195 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2197 &bufSize);
2198 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2199 if (buf)
2200 {
2201 ok(bufSize == constraints2[i].encoded[1] + 2,
2202 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2203 bufSize);
2204 ok(!memcmp(buf, constraints2[i].encoded,
2205 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2206 LocalFree(buf);
2207 }
2208 }
2209 /* Now test with more complex basic constraints */
2210 info.SubjectType.cbData = 0;
2211 info.fPathLenConstraint = FALSE;
2212 info.cSubtreesConstraint = 0;
2213 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2214 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2215 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2216 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2217 if (buf)
2218 {
2219 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2220 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2221 "Unexpected value\n");
2222 LocalFree(buf);
2223 }
2224 /* None of the certs I examined had any subtree constraint, but I test one
2225 * anyway just in case.
2226 */
2227 info.cSubtreesConstraint = 1;
2228 info.rgSubtreesConstraint = &nameBlob;
2229 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2230 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2231 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2232 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2233 if (buf)
2234 {
2235 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2236 ok(!memcmp(buf, constraintWithDomainName,
2237 sizeof(constraintWithDomainName)), "Unexpected value\n");
2238 LocalFree(buf);
2239 }
2240 /* FIXME: test encoding with subject type. */
2241 }
2242
2243 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2244
2245 static void test_decodeBasicConstraints(DWORD dwEncoding)
2246 {
2247 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2248 0xff };
2249 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2250 DWORD i;
2251 BOOL ret;
2252 BYTE *buf = NULL;
2253 DWORD bufSize = 0;
2254
2255 /* First test with simpler info2 */
2256 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2257 {
2258 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2259 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2260 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2261 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2262 GetLastError());
2263 if (buf)
2264 {
2265 CERT_BASIC_CONSTRAINTS2_INFO *info =
2266 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2267
2268 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2269 "Unexpected value for item %d\n", i);
2270 LocalFree(buf);
2271 }
2272 }
2273 /* Check with the order of encoded elements inverted */
2274 buf = (PBYTE)1;
2275 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2276 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2277 &bufSize);
2278 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2279 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2280 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2281 GetLastError());
2282 ok(!buf, "Expected buf to be set to NULL\n");
2283 /* Check with a non-DER bool */
2284 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2285 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2286 &buf, &bufSize);
2287 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2288 if (buf)
2289 {
2290 CERT_BASIC_CONSTRAINTS2_INFO *info =
2291 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2292
2293 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2294 LocalFree(buf);
2295 }
2296 /* Check with a non-basic constraints value */
2297 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2298 encodedCommonName, encodedCommonName[1] + 2,
2299 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2300 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2301 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2302 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2303 GetLastError());
2304 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2305 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2306 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2307 &buf, &bufSize);
2308 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2309 if (buf)
2310 {
2311 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2312
2313 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2314 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2315 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2316 LocalFree(buf);
2317 }
2318 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2319 constraintWithDomainName, sizeof(constraintWithDomainName),
2320 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2321 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322 if (buf)
2323 {
2324 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2325
2326 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2327 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2328 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2329 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2330 {
2331 ok(info->rgSubtreesConstraint[0].cbData ==
2332 sizeof(encodedDomainName), "Wrong size %d\n",
2333 info->rgSubtreesConstraint[0].cbData);
2334 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2335 sizeof(encodedDomainName)), "Unexpected value\n");
2336 }
2337 LocalFree(buf);
2338 }
2339 }
2340
2341 /* These are terrible public keys of course, I'm just testing encoding */
2342 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2343 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2344 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2345 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2346 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2347 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2349 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2350
2351 struct EncodedRSAPubKey
2352 {
2353 const BYTE *modulus;
2354 size_t modulusLen;
2355 const BYTE *encoded;
2356 size_t decodedModulusLen;
2357 };
2358
2359 struct EncodedRSAPubKey rsaPubKeys[] = {
2360 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2361 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2362 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2363 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2364 };
2365
2366 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2367 {
2368 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2369 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2370 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2371 BOOL ret;
2372 BYTE *buf = NULL;
2373 DWORD bufSize = 0, i;
2374
2375 /* Try with a bogus blob type */
2376 hdr->bType = 2;
2377 hdr->bVersion = CUR_BLOB_VERSION;
2378 hdr->reserved = 0;
2379 hdr->aiKeyAlg = CALG_RSA_KEYX;
2380 rsaPubKey->magic = 0x31415352;
2381 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2382 rsaPubKey->pubexp = 65537;
2383 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2384 sizeof(modulus1));
2385
2386 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2387 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388 ok(!ret && GetLastError() == E_INVALIDARG,
2389 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2390 /* Now with a bogus reserved field */
2391 hdr->bType = PUBLICKEYBLOB;
2392 hdr->reserved = 1;
2393 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2394 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2395 if (buf)
2396 {
2397 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2398 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2399 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2400 LocalFree(buf);
2401 }
2402 /* Now with a bogus blob version */
2403 hdr->reserved = 0;
2404 hdr->bVersion = 0;
2405 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2406 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2407 if (buf)
2408 {
2409 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2410 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2411 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2412 LocalFree(buf);
2413 }
2414 /* And with a bogus alg ID */
2415 hdr->bVersion = CUR_BLOB_VERSION;
2416 hdr->aiKeyAlg = CALG_DES;
2417 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2418 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2419 if (buf)
2420 {
2421 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2422 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2423 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2424 LocalFree(buf);
2425 }
2426 /* Check a couple of RSA-related OIDs */
2427 hdr->aiKeyAlg = CALG_RSA_KEYX;
2428 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2429 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2430 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2431 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2432 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2433 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2434 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2435 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2436 /* Finally, all valid */
2437 hdr->aiKeyAlg = CALG_RSA_KEYX;
2438 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2439 {
2440 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2441 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2442 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2443 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2444 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2445 if (buf)
2446 {
2447 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2448 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2449 bufSize);
2450 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2451 "Unexpected value\n");
2452 LocalFree(buf);
2453 }
2454 }
2455 }
2456
2457 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2458 {
2459 DWORD i;
2460 LPBYTE buf = NULL;
2461 DWORD bufSize = 0;
2462 BOOL ret;
2463
2464 /* Try with a bad length */
2465 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2466 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2467 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2468 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2469 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2470 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2471 GetLastError());
2472 /* Try with a couple of RSA-related OIDs */
2473 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2474 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2475 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2476 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2477 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2478 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2479 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2480 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2481 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2482 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2483 /* Now try success cases */
2484 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2485 {
2486 bufSize = 0;
2487 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2488 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2489 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2490 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2491 if (buf)
2492 {
2493 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2494 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2495
2496 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2497 rsaPubKeys[i].decodedModulusLen,
2498 "Wrong size %d\n", bufSize);
2499 ok(hdr->bType == PUBLICKEYBLOB,
2500 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2501 hdr->bType);
2502 ok(hdr->bVersion == CUR_BLOB_VERSION,
2503 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2504 CUR_BLOB_VERSION, hdr->bVersion);
2505 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2506 hdr->reserved);
2507 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2508 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2509 ok(rsaPubKey->magic == 0x31415352,
2510 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2511 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2512 "Wrong bit len %d\n", rsaPubKey->bitlen);
2513 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2514 rsaPubKey->pubexp);
2515 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2516 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2517 "Unexpected modulus\n");
2518 LocalFree(buf);
2519 }
2520 }
2521 }
2522
2523 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2524 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2525 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2526
2527 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2528 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2529 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2530 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2531
2532 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2533 {
2534 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2535 CRYPT_SEQUENCE_OF_ANY seq;
2536 DWORD i;
2537 BOOL ret;
2538 BYTE *buf = NULL;
2539 DWORD bufSize = 0;
2540
2541 /* Encode a homogeneous sequence */
2542 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2543 {
2544 blobs[i].cbData = ints[i].encoded[1] + 2;
2545 blobs[i].pbData = (BYTE *)ints[i].encoded;
2546 }
2547 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2548 seq.rgValue = blobs;
2549
2550 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2551 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2552 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2553 if (buf)
2554 {
2555 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2556 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2557 LocalFree(buf);
2558 }
2559 /* Change the type of the first element in the sequence, and give it
2560 * another go
2561 */
2562 blobs[0].cbData = times[0].encodedTime[1] + 2;
2563 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2564 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2565 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2566 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2567 if (buf)
2568 {
2569 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2570 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2571 "Unexpected value\n");
2572 LocalFree(buf);
2573 }
2574 }
2575
2576 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2577 {
2578 BOOL ret;
2579 BYTE *buf = NULL;
2580 DWORD bufSize = 0;
2581
2582 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2583 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2584 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2585 if (buf)
2586 {
2587 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2588 DWORD i;
2589
2590 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2591 "Wrong elements %d\n", seq->cValue);
2592 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2593 {
2594 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2595 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2596 seq->rgValue[i].cbData);
2597 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2598 ints[i].encoded[1] + 2), "Unexpected value\n");
2599 }
2600 LocalFree(buf);
2601 }
2602 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2603 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2604 &bufSize);
2605 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2606 if (buf)
2607 {
2608 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2609
2610 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2611 "Wrong elements %d\n", seq->cValue);
2612 /* Just check the first element since it's all that changed */
2613 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2614 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2615 seq->rgValue[0].cbData);
2616 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2617 times[0].encodedTime[1] + 2), "Unexpected value\n");
2618 LocalFree(buf);
2619 }
2620 }
2621
2622 struct encodedExtensions
2623 {
2624 CERT_EXTENSIONS exts;
2625 const BYTE *encoded;
2626 };
2627
2628 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2629 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2630 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2631 static CERT_EXTENSION criticalExt =
2632 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2633 static CERT_EXTENSION nonCriticalExt =
2634 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2635 static CHAR oid_short[] = "1.1";
2636 static CERT_EXTENSION extWithShortOid =
2637 { oid_short, FALSE, { 0, NULL } };
2638
2639 static const BYTE ext0[] = { 0x30,0x00 };
2640 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2641 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2642 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2643 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2644 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2645
2646 static const struct encodedExtensions exts[] = {
2647 { { 0, NULL }, ext0 },
2648 { { 1, &criticalExt }, ext1 },
2649 { { 1, &nonCriticalExt }, ext2 },
2650 { { 1, &extWithShortOid }, ext3 }
2651 };
2652
2653 static void test_encodeExtensions(DWORD dwEncoding)
2654 {
2655 DWORD i;
2656
2657 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2658 {
2659 BOOL ret;
2660 BYTE *buf = NULL;
2661 DWORD bufSize = 0;
2662
2663 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2664 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2665 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2666 if (buf)
2667 {
2668 ok(bufSize == exts[i].encoded[1] + 2,
2669 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2670 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2671 "Unexpected value\n");
2672 LocalFree(buf);
2673 }
2674 }
2675 }
2676
2677 static void test_decodeExtensions(DWORD dwEncoding)
2678 {
2679 DWORD i;
2680
2681 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2682 {
2683 BOOL ret;
2684 BYTE *buf = NULL;
2685 DWORD bufSize = 0;
2686
2687 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2688 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2689 NULL, &buf, &bufSize);
2690 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2691 if (buf)
2692 {
2693 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2694 DWORD j;
2695
2696 ok(ext->cExtension == exts[i].exts.cExtension,
2697 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2698 ext->cExtension);
2699 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2700 {
2701 ok(!strcmp(ext->rgExtension[j].pszObjId,
2702 exts[i].exts.rgExtension[j].pszObjId),
2703 "Expected OID %s, got %s\n",
2704 exts[i].exts.rgExtension[j].pszObjId,
2705 ext->rgExtension[j].pszObjId);
2706 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2707 exts[i].exts.rgExtension[j].Value.pbData,
2708 exts[i].exts.rgExtension[j].Value.cbData),
2709 "Unexpected value\n");
2710 }
2711 LocalFree(buf);
2712 }
2713 }
2714 }
2715
2716 /* MS encodes public key info with a NULL if the algorithm identifier's
2717 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2718 * it encodes them by omitting the algorithm parameters. It accepts either
2719 * form for decoding.
2720 */
2721 struct encodedPublicKey
2722 {
2723 CERT_PUBLIC_KEY_INFO info;
2724 const BYTE *encoded;
2725 const BYTE *encodedNoNull;
2726 CERT_PUBLIC_KEY_INFO decoded;
2727 };
2728
2729 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2730 0xe, 0xf };
2731 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2732
2733 static const unsigned char bin64[] = {
2734 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2735 static const unsigned char bin65[] = {
2736 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2737 static const unsigned char bin66[] = {
2738 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2739 static const unsigned char bin67[] = {
2740 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2741 static const unsigned char bin68[] = {
2742 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2743 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2744 static const unsigned char bin69[] = {
2745 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2746 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2747 static const unsigned char bin70[] = {
2748 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2749 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2750 0x0f};
2751 static const unsigned char bin71[] = {
2752 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2753 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2754 0x0f};
2755 static unsigned char bin72[] = { 0x05,0x00};
2756
2757 static CHAR oid_bogus[] = "1.2.3",
2758 oid_rsa[] = szOID_RSA;
2759
2760 static const struct encodedPublicKey pubKeys[] = {
2761 /* with a bogus OID */
2762 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2763 bin64, bin65,
2764 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2765 /* some normal keys */
2766 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2767 bin66, bin67,
2768 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2769 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2770 bin68, bin69,
2771 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2772 /* with add'l parameters--note they must be DER-encoded */
2773 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2774 (BYTE *)aKey, 0 } },
2775 bin70, bin71,
2776 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2777 (BYTE *)aKey, 0 } } },
2778 };
2779
2780 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2781 {
2782 DWORD i;
2783
2784 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2785 {
2786 BOOL ret;
2787 BYTE *buf = NULL;
2788 DWORD bufSize = 0;
2789
2790 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2791 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2792 &bufSize);
2793 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2794 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2795 if (buf)
2796 {
2797 ok(bufSize == pubKeys[i].encoded[1] + 2,
2798 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2799 if (bufSize == pubKeys[i].encoded[1] + 2)
2800 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2801 "Unexpected value\n");
2802 LocalFree(buf);
2803 }
2804 }
2805 }
2806
2807 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2808 const CERT_PUBLIC_KEY_INFO *got)
2809 {
2810 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2811 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2812 got->Algorithm.pszObjId);
2813 ok(expected->Algorithm.Parameters.cbData ==
2814 got->Algorithm.Parameters.cbData,
2815 "Expected parameters of %d bytes, got %d\n",
2816 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2817 if (expected->Algorithm.Parameters.cbData)
2818 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2819 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2820 "Unexpected algorithm parameters\n");
2821 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2822 "Expected public key of %d bytes, got %d\n",
2823 expected->PublicKey.cbData, got->PublicKey.cbData);
2824 if (expected->PublicKey.cbData)
2825 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2826 got->PublicKey.cbData), "Unexpected public key value\n");
2827 }
2828
2829 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2830 {
2831 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2832 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2833 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2834 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2835 DWORD i;
2836 BOOL ret;
2837 BYTE *buf = NULL;
2838 DWORD bufSize = 0;
2839
2840 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2841 {
2842 /* The NULL form decodes to the decoded member */
2843 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2844 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2845 NULL, &buf, &bufSize);
2846 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2847 if (buf)
2848 {
2849 comparePublicKeyInfo(&pubKeys[i].decoded,
2850 (CERT_PUBLIC_KEY_INFO *)buf);
2851 LocalFree(buf);
2852 }
2853 /* The non-NULL form decodes to the original */
2854 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2855 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2856 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2857 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2858 if (buf)
2859 {
2860 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2861 LocalFree(buf);
2862 }
2863 }
2864 /* Test with bogus (not valid DER) parameters */
2865 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2866 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2867 NULL, &buf, &bufSize);
2868 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2869 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2870 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2871 GetLastError());
2872 }
2873
2874 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2875 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2876 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2877 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2878 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2879 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2880 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2881 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2882 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2883 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2884 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2885 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2886 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2887 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2888 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2889 static const BYTE v4Cert[] = {
2890 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2891 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2892 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2893 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2894 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2895 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2896 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2897 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2898 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2899 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2900 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2901 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2902 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2903 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2904 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2905 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2906 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2907 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2908 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2909 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2910 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2911 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2912 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2913 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2914 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2915 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2916 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2917 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2918 static const BYTE v1CertWithPubKey[] = {
2919 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2920 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2921 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2922 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2923 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2924 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2925 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2926 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2927 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2928 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2929 0x01,0x01 };
2930 static const BYTE v1CertWithPubKeyNoNull[] = {
2931 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2932 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2933 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2934 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2935 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2936 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2937 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2938 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2939 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2940 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2941 static const BYTE v1CertWithSubjectKeyId[] = {
2942 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2943 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2944 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2945 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2946 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2947 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2948 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2949 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2950 0x4c,0x61,0x6e,0x67,0x00 };
2951 static const BYTE v1CertWithIssuerUniqueId[] = {
2952 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2953 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2954 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2955 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2956 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2957 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2958 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2959 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2960 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2961 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2962 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2963 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2964 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2965 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2966 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2967 0x01,0x01,0xff,0x02,0x01,0x01 };
2968 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2969 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2970 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2971 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2972 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2973 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2974 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2975 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2976 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2977 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2978 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2979 0xff,0x02,0x01,0x01 };
2980
2981 static const BYTE serialNum[] = { 0x01 };
2982
2983 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2984 {
2985 BOOL ret;
2986 BYTE *buf = NULL;
2987 DWORD size = 0;
2988 CERT_INFO info = { 0 };
2989 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2990 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2991 CERT_EXTENSION ext;
2992
2993 if (0)
2994 {
2995 /* Test with NULL pvStructInfo (crashes on win9x) */
2996 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2997 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2998 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2999 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3000 }
3001 /* Test with a V1 cert */
3002 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3003 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3004 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3005 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3006 if (buf)
3007 {
3008 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3009 v1Cert[1] + 2, size);
3010 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3011 LocalFree(buf);
3012 }
3013 /* Test v2 cert */
3014 info.dwVersion = CERT_V2;
3015 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3016 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3017 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3018 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3019 if (buf)
3020 {
3021 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3022 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3023 LocalFree(buf);
3024 }
3025 /* Test v3 cert */
3026 info.dwVersion = CERT_V3;
3027 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3028 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3029 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3030 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3031 if (buf)
3032 {
3033 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3034 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3035 LocalFree(buf);
3036 }
3037 /* A v4 cert? */
3038 info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3039 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3040 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3041 if (buf)
3042 {
3043 ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3044 ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3045 LocalFree(buf);
3046 }
3047 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3048 * API doesn't prevent it)
3049 */
3050 info.dwVersion = CERT_V1;
3051 info.cExtension = 1;
3052 info.rgExtension = &criticalExt;
3053 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3054 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3055 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3056 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3057 if (buf)
3058 {
3059 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3060 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3061 LocalFree(buf);
3062 }
3063 /* test v1 cert with a serial number */
3064 info.SerialNumber.cbData = sizeof(serialNum);
3065 info.SerialNumber.pbData = (BYTE *)serialNum;
3066 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3067 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3068 if (buf)
3069 {
3070 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3071 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3072 LocalFree(buf);
3073 }
3074 /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3075 info.dwVersion = CERT_V1;
3076 info.cExtension = 0;
3077 info.IssuerUniqueId.cbData = sizeof(serialNum);
3078 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3079 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3080 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3081 ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3082 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3083 if (buf)
3084 {
3085 ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3086 ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3087 "Got unexpected value\n");
3088 LocalFree(buf);
3089 }
3090 /* Test v1 cert with an issuer name, a subject name, and a serial number */
3091 info.IssuerUniqueId.cbData = 0;
3092 info.IssuerUniqueId.pbData = NULL;
3093 info.cExtension = 1;
3094 info.rgExtension = &criticalExt;
3095 info.Issuer.cbData = sizeof(encodedCommonName);
3096 info.Issuer.pbData = (BYTE *)encodedCommonName;
3097 info.Subject.cbData = sizeof(encodedCommonName);
3098 info.Subject.pbData = (BYTE *)encodedCommonName;
3099 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3100 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3101 if (buf)
3102 {
3103 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3104 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3105 LocalFree(buf);
3106 }
3107 /* Add a public key */
3108 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3109 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3110 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3111 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3112 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3113 if (buf)
3114 {
3115 ok(size == sizeof(v1CertWithPubKey) ||
3116 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3117 if (size == sizeof(v1CertWithPubKey))
3118 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3119 else if (size == sizeof(v1CertWithPubKeyNoNull))
3120 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3121 "Got unexpected value\n");
3122 LocalFree(buf);
3123 }
3124 /* Again add an issuer unique id */
3125 info.IssuerUniqueId.cbData = sizeof(serialNum);
3126 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3127 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3128 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3129 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3130 if (buf)
3131 {
3132 ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3133 size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3134 "Wrong size %d\n", size);
3135 if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3136 ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3137 size), "unexpected value\n");
3138 else if (size ==
3139 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3140 ok(!memcmp(buf,
3141 v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3142 "unexpected value\n");
3143 LocalFree(buf);
3144 }
3145 /* Remove the public key, and add a subject key identifier extension */
3146 info.IssuerUniqueId.cbData = 0;
3147 info.IssuerUniqueId.pbData = NULL;
3148 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3149 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3150 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3151 ext.pszObjId = oid_subject_key_identifier;
3152 ext.fCritical = FALSE;
3153 ext.Value.cbData = sizeof(octetCommonNameValue);
3154 ext.Value.pbData = octetCommonNameValue;
3155 info.cExtension = 1;
3156 info.rgExtension = &ext;
3157 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3159 if (buf)
3160 {
3161 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3162 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3163 LocalFree(buf);
3164 }
3165 }
3166
3167 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3168 {
3169 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3170 v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3171 BOOL ret;
3172 BYTE *buf = NULL;
3173 DWORD size = 0, i;
3174
3175 /* Test with NULL pbEncoded */
3176 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3177 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3178 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3179 GetLastError() == OSS_BAD_ARG /* Win9x */),
3180 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3181 if (0)
3182 {
3183 /* Crashes on win9x */
3184 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3185 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3186 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3187 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3188 }
3189 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3190 * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3191 * serial number, an issuer, a subject, and a public key.
3192 */
3193 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3194 {
3195 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3196 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3197 &buf, &size);
3198 ok(!ret, "Expected failure\n");
3199 }
3200 /* The following succeeds, even though v1 certs are not allowed to have
3201 * extensions.
3202 */
3203 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3204 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3205 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3206 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3207 if (ret)
3208 {
3209 CERT_INFO *info = (CERT_INFO *)buf;
3210
3211 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3212 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3213 info->dwVersion);
3214 ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3215 info->cExtension);
3216 LocalFree(buf);
3217 }
3218 /* The following also succeeds, even though V1 certs are not allowed to
3219 * have issuer unique ids.
3220 */
3221 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3222 v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3223 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3224 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3225 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3226 if (ret)
3227 {
3228 CERT_INFO *info = (CERT_INFO *)buf;
3229
3230 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3231 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3232 info->dwVersion);
3233 ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3234 "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3235 ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3236 "unexpected issuer unique id value\n");
3237 LocalFree(buf);
3238 }
3239 /* Now check with serial number, subject and issuer specified */
3240 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3241 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3242 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3243 if (buf)
3244 {
3245 CERT_INFO *info = (CERT_INFO *)buf;
3246
3247 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3248 ok(info->SerialNumber.cbData == 1,
3249 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3250 ok(*info->SerialNumber.pbData == *serialNum,
3251 "Expected serial number %d, got %d\n", *serialNum,
3252 *info->SerialNumber.pbData);
3253 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3254 "Wrong size %d\n", info->Issuer.cbData);
3255 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3256 "Unexpected issuer\n");
3257 ok(info->Subject.cbData == sizeof(encodedCommonName),
3258 "Wrong size %d\n", info->Subject.cbData);
3259 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3260 info->Subject.cbData), "Unexpected subject\n");
3261 LocalFree(buf);
3262 }
3263 /* Check again with pub key specified */
3264 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3265 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3266 &buf, &size);
3267 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3268 if (buf)
3269 {
3270 CERT_INFO *info = (CERT_INFO *)buf;
3271
3272 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3273 ok(info->SerialNumber.cbData == 1,
3274 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3275 ok(*info->SerialNumber.pbData == *serialNum,
3276 "Expected serial number %d, got %d\n", *serialNum,
3277 *info->SerialNumber.pbData);
3278 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3279 "Wrong size %d\n", info->Issuer.cbData);
3280 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3281 "Unexpected issuer\n");
3282 ok(info->Subject.cbData == sizeof(encodedCommonName),
3283 "Wrong size %d\n", info->Subject.cbData);
3284 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3285 info->Subject.cbData), "Unexpected subject\n");
3286 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3287 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3288 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3289 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3290 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3291 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3292 sizeof(aKey)), "Unexpected public key\n");
3293 LocalFree(buf);
3294 }
3295 }
3296
3297 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3298 0xe, 0xf };
3299
3300 static const BYTE signedBigCert[] = {
3301 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3302 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3303 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3304 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3305 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3306 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3307 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3308 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3309 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3310 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3311 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3312 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3313
3314 static void test_encodeCert(DWORD dwEncoding)
3315 {
3316 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3317 * also that bigCert is a NULL-terminated string, so don't count its
3318 * last byte (otherwise the signed cert won't decode.)
3319 */
3320 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3321 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3322 BOOL ret;
3323 BYTE *buf = NULL;
3324 DWORD bufSize = 0;
3325
3326 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3327 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3328 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3329 if (buf)
3330 {
3331 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3332 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3333 LocalFree(buf);
3334 }
3335 }
3336
3337 static void test_decodeCert(DWORD dwEncoding)
3338 {
3339 BOOL ret;
3340 BYTE *buf = NULL;
3341 DWORD size = 0;
3342
3343 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3344 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3345 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3346 if (buf)
3347 {
3348 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3349
3350 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3351 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3352 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3353 "Unexpected cert\n");
3354 ok(info->Signature.cbData == sizeof(hash),
3355 "Wrong signature size %d\n", info->Signature.cbData);
3356 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3357 "Unexpected signature\n");
3358 LocalFree(buf);
3359 }
3360 /* A signed cert decodes as a CERT_INFO too */
3361 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3362 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3363 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3364 if (buf)
3365 {
3366 CERT_INFO *info = (CERT_INFO *)buf;
3367
3368 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3369 ok(info->SerialNumber.cbData == 1,
3370 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3371 ok(*info->SerialNumber.pbData == *serialNum,
3372 "Expected serial number %d, got %d\n", *serialNum,
3373 *info->SerialNumber.pbData);
3374 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3375 "Wrong size %d\n", info->Issuer.cbData);
3376 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3377 "Unexpected issuer\n");
3378 ok(info->Subject.cbData == sizeof(encodedCommonName),
3379 "Wrong size %d\n", info->Subject.cbData);
3380 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3381 info->Subject.cbData), "Unexpected subject\n");
3382 LocalFree(buf);
3383 }
3384 }
3385
3386 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3387 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3388 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3389 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3390 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3391 0x00, 0x03 };
3392 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3393 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3394 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3395 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3396 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3397 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3398 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3399 0x2e, 0x6f, 0x72, 0x67 };
3400 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3401 CRL_REASON_AFFILIATION_CHANGED;
3402
3403 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3404 {
3405 CRL_DIST_POINTS_INFO info = { 0 };
3406 CRL_DIST_POINT point = { { 0 } };
3407 CERT_ALT_NAME_ENTRY entry = { 0 };
3408 BOOL ret;
3409 BYTE *buf = NULL;
3410 DWORD size = 0;
3411
3412 /* Test with an empty info */
3413 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3414 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3415 ok(!ret && GetLastError() == E_INVALIDARG,
3416 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3417 /* Test with one empty dist point */
3418 info.cDistPoint = 1;
3419 info.rgDistPoint = &point;
3420 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3421 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3422 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3423 if (buf)
3424 {
3425 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3426 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3427 LocalFree(buf);
3428 }
3429 /* A dist point with an invalid name */
3430 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3431 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3432 U(entry).pwszURL = (LPWSTR)nihongoURL;
3433 U(point.DistPointName).FullName.cAltEntry = 1;
3434 U(point.DistPointName).FullName.rgAltEntry = &entry;
3435 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3436 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3437 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3438 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3439 /* The first invalid character is at index 7 */
3440 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3441 "Expected invalid char at index 7, got %d\n",
3442 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3443 /* A dist point with (just) a valid name */
3444 U(entry).pwszURL = (LPWSTR)url;
3445 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3446 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3447 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3448 if (buf)
3449 {
3450 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3451 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3452 LocalFree(buf);
3453 }
3454 /* A dist point with (just) reason flags */
3455 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3456 point.ReasonFlags.cbData = sizeof(crlReason);
3457 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3458 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3459 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3460 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3461 if (buf)
3462 {
3463 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3464 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3465 LocalFree(buf);
3466 }
3467 /* A dist point with just an issuer */
3468 point.ReasonFlags.cbData = 0;
3469 point.CRLIssuer.cAltEntry = 1;
3470 point.CRLIssuer.rgAltEntry = &entry;
3471 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3473 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3474 if (buf)
3475 {
3476 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3477 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3478 LocalFree(buf);
3479 }
3480 /* A dist point with both a name and an issuer */
3481 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3482 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3483 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3484 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3485 if (buf)
3486 {
3487 ok(size == sizeof(distPointWithUrlAndIssuer),
3488 "Wrong size %d\n", size);
3489 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3490 LocalFree(buf);
3491 }
3492 }
3493
3494 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3495 {
3496 BOOL ret;
3497 BYTE *buf = NULL;
3498 DWORD size = 0;
3499 PCRL_DIST_POINTS_INFO info;
3500 PCRL_DIST_POINT point;
3501 PCERT_ALT_NAME_ENTRY entry;
3502
3503 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3504 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3505 &buf, &size);
3506 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3507 if (ret)
3508 {
3509 info = (PCRL_DIST_POINTS_INFO)buf;
3510 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3511 "Wrong size %d\n", size);
3512 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3513 info->cDistPoint);
3514 point = info->rgDistPoint;
3515 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3516 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3517 point->DistPointName.dwDistPointNameChoice);
3518 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3519 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3520 LocalFree(buf);
3521 }
3522 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3523 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3524 &buf, &size);
3525 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3526 if (ret)
3527 {
3528 info = (PCRL_DIST_POINTS_INFO)buf;
3529 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3530 "Wrong size %d\n", size);
3531 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3532 info->cDistPoint);
3533 point = info->rgDistPoint;
3534 ok(point->DistPointName.dwDistPointNameChoice ==
3535 CRL_DIST_POINT_FULL_NAME,
3536 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3537 point->DistPointName.dwDistPointNameChoice);
3538 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3539 "Expected 1 name entry, got %d\n",
3540 U(point->DistPointName).FullName.cAltEntry);
3541 entry = U(point->DistPointName).FullName.rgAltEntry;
3542 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3543 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3544 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3545 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3546 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3547 LocalFree(buf);
3548 }
3549 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3550 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3551 NULL, &buf, &size);
3552 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3553 if (ret)
3554 {
3555 info = (PCRL_DIST_POINTS_INFO)buf;
3556 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3557 "Wrong size %d\n", size);
3558 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3559 info->cDistPoint);
3560 point = info->rgDistPoint;
3561 ok(point->DistPointName.dwDistPointNameChoice ==
3562 CRL_DIST_POINT_NO_NAME,
3563 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3564 point->DistPointName.dwDistPointNameChoice);
3565 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3566 "Expected reason length\n");
3567 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3568 "Unexpected reason\n");
3569 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3570 LocalFree(buf);
3571 }
3572 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3573 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3574 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3575 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3576 if (ret)
3577 {
3578 info = (PCRL_DIST_POINTS_INFO)buf;
3579 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3580 "Wrong size %d\n", size);
3581 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3582 info->cDistPoint);
3583 point = info->rgDistPoint;
3584 ok(point->DistPointName.dwDistPointNameChoice ==
3585 CRL_DIST_POINT_FULL_NAME,
3586 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3587 point->DistPointName.dwDistPointNameChoice);
3588 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3589 "Expected 1 name entry, got %d\n",
3590 U(point->DistPointName).FullName.cAltEntry);
3591 entry = U(point->DistPointName).FullName.rgAltEntry;
3592 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3593 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3594 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3595 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3596 ok(point->CRLIssuer.cAltEntry == 1,
3597 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3598 entry = point->CRLIssuer.rgAltEntry;
3599 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3600 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3601 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3602 LocalFree(buf);
3603 }
3604 }
3605
3606 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3607 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3608 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3609 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3610 0x67 };
3611
3612 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3613 {
3614 BOOL ret;
3615 BYTE *buf = NULL;
3616 DWORD size = 0;
3617 CRL_ISSUING_DIST_POINT point = { { 0 } };
3618 CERT_ALT_NAME_ENTRY entry;
3619
3620 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3621 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3622 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3623 {
3624 skip("no X509_ISSUING_DIST_POINT encode support\n");
3625 return;
3626 }
3627 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3628 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3629 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3630 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3631 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3632 if (buf)
3633 {
3634 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3635 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3636 LocalFree(buf);
3637 }
3638 /* nonsensical flags */
3639 point.fOnlyContainsUserCerts = TRUE;
3640 point.fOnlyContainsCACerts = TRUE;
3641 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3642 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3643 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3644 if (buf)
3645 {
3646 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3647 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3648 LocalFree(buf);
3649 }
3650 /* unimplemented name type */
3651 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3652 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3653 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3654 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655 ok(!ret && GetLastError() == E_INVALIDARG,
3656 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3657 /* empty name */
3658 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3659 U(point.DistPointName).FullName.cAltEntry = 0;
3660 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3661 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3662 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3663 if (buf)
3664 {
3665 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3666 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3667 LocalFree(buf);
3668 }
3669 /* name with URL entry */
3670 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3671 U(entry).pwszURL = (LPWSTR)url;
3672 U(point.DistPointName).FullName.cAltEntry = 1;
3673 U(point.DistPointName).FullName.rgAltEntry = &entry;
3674 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3675 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3676 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3677 if (buf)
3678 {
3679 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3680 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3681 LocalFree(buf);
3682 }
3683 }
3684
3685 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3686 const CERT_ALT_NAME_ENTRY *got)
3687 {
3688 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3689 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3690 got->dwAltNameChoice);
3691 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3692 {
3693 switch (got->dwAltNameChoice)
3694 {
3695 case CERT_ALT_NAME_RFC822_NAME:
3696 case CERT_ALT_NAME_DNS_NAME:
3697 case CERT_ALT_NAME_EDI_PARTY_NAME:
3698 case CERT_ALT_NAME_URL:
3699 case CERT_ALT_NAME_REGISTERED_ID:
3700 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3701 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3702 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3703 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3704 "Unexpected name\n");
3705 break;
3706 case CERT_ALT_NAME_X400_ADDRESS:
3707 case CERT_ALT_NAME_DIRECTORY_NAME:
3708 case CERT_ALT_NAME_IP_ADDRESS:
3709 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3710 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3711 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3712 U(*got).IPAddress.cbData), "Unexpected value\n");
3713 break;
3714 }
3715 }
3716 }
3717
3718 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3719 const CERT_ALT_NAME_INFO *got)
3720 {
3721 DWORD i;
3722
3723 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3724 expected->cAltEntry, got->cAltEntry);
3725 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3726 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3727 }
3728
3729 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3730 const CRL_DIST_POINT_NAME *got)
3731 {
3732 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3733 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3734 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3735 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3736 }
3737
3738 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3739 const CRL_ISSUING_DIST_POINT *got)
3740 {
3741 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3742 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3743 "Unexpected fOnlyContainsUserCerts\n");
3744 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3745 "Unexpected fOnlyContainsCACerts\n");
3746 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3747 "Unexpected reason flags\n");
3748 ok(got->fIndirectCRL == expected->fIndirectCRL,
3749 "Unexpected fIndirectCRL\n");
3750 }
3751
3752 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3753 {
3754 BOOL ret;
3755 BYTE *buf = NULL;
3756 DWORD size = 0;
3757 CRL_ISSUING_DIST_POINT point = { { 0 } };
3758
3759 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3760 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3761 &buf, &size);
3762 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3763 {
3764 skip("no X509_ISSUING_DIST_POINT decode support\n");
3765 return;
3766 }
3767 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3768 if (ret)
3769 {
3770 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3771 LocalFree(buf);
3772 }
3773 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3774 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3775 &buf, &size);
3776 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3777 if (ret)
3778 {
3779 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3780 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3781 LocalFree(buf);
3782 }
3783 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3784 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3785 &buf, &size);
3786 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3787 if (ret)
3788 {
3789 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3790 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3791 U(point.DistPointName).FullName.cAltEntry = 0;
3792 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3793 LocalFree(buf);
3794 }
3795 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3796 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3797 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3798 if (ret)
3799 {
3800 CERT_ALT_NAME_ENTRY entry;
3801
3802 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3803 U(entry).pwszURL = (LPWSTR)url;
3804 U(point.DistPointName).FullName.cAltEntry = 1;
3805 U(point.DistPointName).FullName.rgAltEntry = &entry;
3806 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3807 LocalFree(buf);
3808 }
3809 }
3810
3811 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3812 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3813 0x30, 0x5a };
3814 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3815 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3816 0x30, 0x30, 0x30, 0x30, 0x5a };
3817 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3818 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3819 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3820 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3821 0x5a };
3822 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3823 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3824 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3825 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3826 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3827 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3828 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3829 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3830 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3831 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3832 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3833 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3834 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3835 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3836 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3837 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3838 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3839 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3840 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3841 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3842 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3843 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3844 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3845 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3846 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3847 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3848 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3849 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3850 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3851 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3852 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3853 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3854 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3855
3856 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3857 {
3858 BOOL ret;
3859 BYTE *buf = NULL;
3860 DWORD size = 0;
3861 CRL_INFO info = { 0 };
3862 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3863
3864 /* Test with a V1 CRL */
3865 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3866 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3867 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3868 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3869 if (buf)
3870 {
3871 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3872 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3873 LocalFree(buf);
3874 }
3875 /* Test v2 CRL */
3876 info.dwVersion = CRL_V2;
3877 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3878 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3879 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3880 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3881 if (buf)
3882 {
3883 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3884 v2CRL[1] + 2, size);
3885 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3886 LocalFree(buf);
3887 }
3888 /* v1 CRL with a name */
3889 info.dwVersion = CRL_V1;
3890 info.Issuer.cbData = sizeof(encodedCommonName);
3891 info.Issuer.pbData = (BYTE *)encodedCommonName;
3892 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3893 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3894 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3895 if (buf)
3896 {
3897 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3898 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3899 LocalFree(buf);
3900 }
3901 if (0)
3902 {
3903 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3904 info.cCRLEntry = 1;
3905 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3906 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3907 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3908 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3909 }
3910 /* now set an empty entry */
3911 info.cCRLEntry = 1;
3912 info.rgCRLEntry = &entry;
3913 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3914 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3915 if (buf)
3916 {
3917 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3918 "Wrong size %d\n", size);
3919 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3920 "Got unexpected value\n");
3921 LocalFree(buf);
3922 }
3923 /* an entry with a serial number */
3924 entry.SerialNumber.cbData = sizeof(serialNum);
3925 entry.SerialNumber.pbData = (BYTE *)serialNum;
3926 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3927 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3928 if (buf)
3929 {
3930 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3931 "Wrong size %d\n", size);
3932 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3933 "Got unexpected value\n");
3934 LocalFree(buf);
3935 }
3936 /* an entry with an extension */
3937 entry.cExtension = 1;
3938 entry.rgExtension = &criticalExt;
3939 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3940 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3941 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3942 if (buf)
3943 {
3944 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3945 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3946 LocalFree(buf);
3947 }
3948 /* a CRL with an extension */
3949 entry.cExtension = 0;
3950 info.cExtension = 1;
3951 info.rgExtension = &criticalExt;
3952 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3953 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3954 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3955 if (buf)
3956 {
3957 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3958 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3959 LocalFree(buf);
3960 }
3961 /* a v2 CRL with an extension, this time non-critical */
3962 info.dwVersion = CRL_V2;
3963 info.rgExtension = &nonCriticalExt;
3964 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3965 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3966 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3967 if (buf)
3968 {
3969 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3970 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3971 LocalFree(buf);
3972 }
3973 }
3974
3975 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3976 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3977 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3978 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3979 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3980 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3981 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3982 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3983 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3984 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3985 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3986 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3987 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3988 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3989 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3990 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3991 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3992 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3993 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3994 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3995 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3996 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3997 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3998 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3999 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4000 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4001 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4002 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4003 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4004 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4005 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4006 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4007 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4008 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4009 0xcd };
4010 static const BYTE verisignCRLWithLotsOfEntries[] = {
4011 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4012 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4013 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4014 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4015 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4016 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4017 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4018 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4019 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4020 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4021 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4022 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4023 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4024 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4025 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4026 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4027 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4028 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4029 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4030 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4031 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4032 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4033 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4034 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4035 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4036 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4037 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4038 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4039 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4040 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4041 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4042 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4043 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4044 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4045 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4046 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4047 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4048 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4049 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4050 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4051 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4052 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4053 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4054 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4055 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4056 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4057 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4058 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4059 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4060 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4061 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4062 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4063 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4064 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4065 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4066 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4067 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4068 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4069 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4070 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4071 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4072 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4073 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4074 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4075 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4076 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4077 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4078 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4079 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4080 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4081 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4082 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4083 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4084 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4085 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4086 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4087 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4088 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4089 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4090 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4091 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4092 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4093 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4094 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4095 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4096 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4097 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4098 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4099 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4100 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4101 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4102 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4103 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4104 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4105 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4106 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4107 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4108 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4109 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4110 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4111 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4112 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4113 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4114 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4115 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4116 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4117 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4118 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4119 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4120 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4121 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4122 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4123 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4124 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4125 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4126 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4127 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4128 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4129 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4130 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4131 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4132 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4133 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4134 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4135 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4136 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4137 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4138 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4139 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4140 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4141 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4142 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4143 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4144 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4145 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4146 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4147 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4148 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4149 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4150 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4151 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4152 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4153 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4154 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4155 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4156 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4157 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4158 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4159 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4160 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4161 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4162 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4163 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4164 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4165 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4166 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4167 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4168 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4169 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4170 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4171 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4172 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4173 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4174 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4175 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4176 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4177 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4178 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4179 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4180 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4181 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4182 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4183 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4184 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4185 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4186 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4187 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4188 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4189 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4190 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4191 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4192 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4193 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4194 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4195 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4196 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4197 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4198 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4199 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4200 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4201 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4202 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4203 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4204 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4205 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4206 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4207 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4208 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4209 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4210 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4211 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4212 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4213 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4214 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4215 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4216 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4217 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4218 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4219 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4220 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4221 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4222 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4223 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4224 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4225 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4226 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4227 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4228 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4229 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4230 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4231 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4232 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4233 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4234 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4235 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4236 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4237 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4238 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4239 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4240 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4241 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4242 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4243 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4244 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4245 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4246 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4247 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4248 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4249 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4250 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4251 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4252 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4253 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4254 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4255 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4256 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4257 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4258 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4259 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4260 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4261 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4262 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4263 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4264 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4265 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4266 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4267 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4268 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4269 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4270 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4271 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4272 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4273 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4274 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4275 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4276 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4277 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4278 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4279 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4280 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4281 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4282 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4283 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4284 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4285 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4286 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4287 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4288 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4289 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4290 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4291 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4292 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4293 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4294 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4295 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4296 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4297 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4298 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4299 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4300 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4301 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4302 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4303 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4304 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4305 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4306 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4307 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4308 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4309 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4310 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4311 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4312 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4313 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4314 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4315 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4316 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4317 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4318 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4319 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4320 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4321 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4322 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4323 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4324 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4325 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4326 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4327 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4328 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4329 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4330 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4331 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4332 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4333 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4334 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4335 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4336 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4337 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4338 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4339 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4340 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4341 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4342 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4343 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4344 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4345 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4346 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4347 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4348 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4349 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4350 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4351 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4352 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4353 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4354 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4355 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4356 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4357 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4358 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4359 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4360 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4361 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4362 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4363 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4364 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4365 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4366 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4367 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4368 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4369 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4370 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4371 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4372 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4373 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4374 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4375 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4376 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4377 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4378 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4379 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4380 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4381 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4382 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4383 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4384 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4385 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4386 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4387 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4388 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4389 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4390 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4391 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4392 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4393 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4394 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4395 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4396 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4397 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4398 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4399 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4400 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4401 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4402 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4403 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4404 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4405 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4406 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4407 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4408 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4409 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4410 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4411 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4412 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4413 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4414 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4415 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4416 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4417 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4418 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4419 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4420 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4421 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4422 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4423 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4424 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4425 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4426 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4427 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4428 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4429 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4430 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4431 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4432 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4433 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4434 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4435 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4436 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4437 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4438 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4439 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4440 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4441 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4442 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4443 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4444 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4445 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4446 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4447 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4448 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4449 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4450 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4451 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4452 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4453 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4454 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4455 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4456 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4457 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4458 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4459 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4460 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4461 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4462 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4463 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4464 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4465 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4466 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4467 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4468 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4469 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4470 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4471 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4472 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4473 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4474 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4475 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4476 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4477 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4478 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4479 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4480 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4481 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4482 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4483 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4484 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4485 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4486 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4487 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4488 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4489 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4490 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4491 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4492 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4493 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4494 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4495 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4496 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4497 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4498 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4499 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4500 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4501 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4502 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4503 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4504 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4505 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4506 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4507 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4508 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4509 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4510 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4511 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4512 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4513 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4514 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4515 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4516 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4517 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4518 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4519
4520 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4521 {
4522 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4523 BOOL ret;
4524 BYTE *buf = NULL;
4525 DWORD size = 0, i;
4526
4527 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4528 {
4529 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4530 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4531 &buf, &size);
4532 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4533 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4534 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4535 GetLastError());
4536 }
4537 /* at a minimum, a CRL must contain an issuer: */
4538 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4539 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4540 &buf, &size);
4541 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4542 if (buf)
4543 {
4544 CRL_INFO *info = (CRL_INFO *)buf;
4545
4546 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4547 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4548 info->cCRLEntry);
4549 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4550 "Wrong issuer size %d\n", info->Issuer.cbData);
4551 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4552 "Unexpected issuer\n");
4553 LocalFree(buf);
4554 }
4555 /* check decoding with an empty CRL entry */
4556 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4557 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4558 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4559 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4560 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4561 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4562 GetLastError());
4563 /* with a real CRL entry */
4564 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4565 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4566 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4567 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4568 if (buf)
4569 {
4570 CRL_INFO *info = (CRL_INFO *)buf;
4571 CRL_ENTRY *entry;
4572
4573 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4574 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4575 info->cCRLEntry);
4576 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4577 entry = info->rgCRLEntry;
4578 ok(entry->SerialNumber.cbData == 1,
4579 "Expected serial number size 1, got %d\n",
4580 entry->SerialNumber.cbData);
4581 ok(*entry->SerialNumber.pbData == *serialNum,
4582 "Expected serial number %d, got %d\n", *serialNum,
4583 *entry->SerialNumber.pbData);
4584 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4585 "Wrong issuer size %d\n", info->Issuer.cbData);
4586 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4587 "Unexpected issuer\n");
4588 LocalFree(buf);
4589 }
4590 /* a real CRL from verisign that has extensions */
4591 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4592 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4593 NULL, &buf, &size);
4594 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4595 if (buf)
4596 {
4597 CRL_INFO *info = (CRL_INFO *)buf;
4598 CRL_ENTRY *entry;
4599
4600 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4601 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4602 info->cCRLEntry);
4603 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4604 entry = info->rgCRLEntry;
4605 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4606 info->cExtension);
4607 LocalFree(buf);
4608 }
4609 /* another real CRL from verisign that has lots of entries */
4610 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4611 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4612 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4613 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4614 if (buf)
4615 {
4616 CRL_INFO *info = (CRL_INFO *)buf;
4617
4618 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4619 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4620 info->cCRLEntry);
4621 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4622 info->cExtension);
4623 LocalFree(buf);
4624 }
4625 /* and finally, with an extension */
4626 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4627 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4628 NULL, &buf, &size);
4629 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4630 if (buf)
4631 {
4632 CRL_INFO *info = (CRL_INFO *)buf;
4633 CRL_ENTRY *entry;
4634
4635 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4636 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4637 info->cCRLEntry);
4638 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4639 entry = info->rgCRLEntry;
4640 ok(entry->SerialNumber.cbData == 1,
4641 "Expected serial number size 1, got %d\n",
4642 entry->SerialNumber.cbData);
4643 ok(*entry->SerialNumber.pbData == *serialNum,
4644 "Expected serial number %d, got %d\n", *serialNum,
4645 *entry->SerialNumber.pbData);
4646 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4647 "Wrong issuer size %d\n", info->Issuer.cbData);
4648 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4649 "Unexpected issuer\n");
4650 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4651 info->cExtension);
4652 LocalFree(buf);
4653 }
4654 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4655 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4656 NULL, &buf, &size);
4657 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4658 if (buf)
4659 {
4660 CRL_INFO *info = (CRL_INFO *)buf;
4661
4662 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4663 info->cExtension);
4664 LocalFree(buf);
4665 }
4666 }
4667
4668 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4669 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4670 static const BYTE encodedUsage[] = {
4671 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4672 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4673 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4674
4675 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4676 {
4677 BOOL ret;
4678 BYTE *buf = NULL;
4679 DWORD size = 0;
4680 CERT_ENHKEY_USAGE usage;
4681
4682 /* Test with empty usage */
4683 usage.cUsageIdentifier = 0;
4684 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4685 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4686 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4687 if (buf)
4688 {
4689 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4690 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4691 LocalFree(buf);
4692 }
4693 /* Test with a few usages */
4694 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4695 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4696 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4697 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4698 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4699 if (buf)
4700 {
4701 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4702 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4703 LocalFree(buf);
4704 }
4705 }
4706
4707 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4708 {
4709 BOOL ret;
4710 LPBYTE buf = NULL;
4711 DWORD size = 0;
4712
4713 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4714 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4715 &buf, &size);
4716 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4717 if (buf)
4718 {
4719 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4720
4721 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4722 "Wrong size %d\n", size);
4723 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4724 usage->cUsageIdentifier);
4725 LocalFree(buf);
4726 }
4727 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4728 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4729 &buf, &size);
4730 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4731 if (buf)
4732 {
4733 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4734 DWORD i;
4735
4736 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4737 "Wrong size %d\n", size);
4738 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4739 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4740 for (i = 0; i < usage->cUsageIdentifier; i++)
4741 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4742 "Expected OID %s, got %s\n", keyUsages[i],
4743 usage->rgpszUsageIdentifier[i]);
4744 LocalFree(buf);
4745 }
4746 }
4747
4748 static BYTE keyId[] = { 1,2,3,4 };
4749 static const BYTE authorityKeyIdWithId[] = {
4750 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4751 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4752 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4753 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4754 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4755
4756 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4757 {
4758 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4759 BOOL ret;
4760 BYTE *buf = NULL;
4761 DWORD size = 0;
4762
4763 /* Test with empty id */
4764 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4765 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4766 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4767 if (buf)
4768 {
4769 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4770 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4771 LocalFree(buf);
4772 }
4773 /* With just a key id */
4774 info.KeyId.cbData = sizeof(keyId);
4775 info.KeyId.pbData = keyId;
4776 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4777 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4778 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4779 if (buf)
4780 {
4781 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4782 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4783 LocalFree(buf);
4784 }
4785 /* With just an issuer */
4786 info.KeyId.cbData = 0;
4787 info.CertIssuer.cbData = sizeof(encodedCommonName);
4788 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4789 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4790 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4791 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4792 if (buf)
4793 {
4794 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4795 size);
4796 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4797 LocalFree(buf);
4798 }
4799 /* With just a serial number */
4800 info.CertIssuer.cbData = 0;
4801 info.CertSerialNumber.cbData = sizeof(serialNum);
4802 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4803 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4804 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4805 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4806 if (buf)
4807 {
4808 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4809 size);
4810 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4811 LocalFree(buf);
4812 }
4813 }
4814
4815 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4816 {
4817 BOOL ret;
4818 LPBYTE buf = NULL;
4819 DWORD size = 0;
4820
4821 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4822 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4823 &buf, &size);
4824 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4825 if (buf)
4826 {
4827 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4828
4829 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4830 size);
4831 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4832 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4833 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4834 LocalFree(buf);
4835 }
4836 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4837 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4838 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4839 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4840 if (buf)
4841 {
4842 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4843
4844 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4845 size);
4846 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4847 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4848 "Unexpected key id\n");
4849 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4850 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4851 LocalFree(buf);
4852 }
4853 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4854 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4855 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4856 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4857 if (buf)
4858 {
4859 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4860
4861 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4862 size);
4863 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4864 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4865 "Unexpected issuer len\n");
4866 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4867 sizeof(encodedCommonName)), "Unexpected issuer\n");
4868 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4869 LocalFree(buf);
4870 }
4871 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4872 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4873 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4874 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4875 if (buf)
4876 {
4877 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4878
4879 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4880 size);
4881 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4882 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4883 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4884 "Unexpected serial number len\n");
4885 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4886 "Unexpected serial number\n");
4887 LocalFree(buf);
4888 }
4889 }
4890
4891 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4892 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4893 0x6f,0x72,0x67 };
4894
4895 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4896 {
4897 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4898 CERT_ALT_NAME_ENTRY entry = { 0 };
4899 BOOL ret;
4900 BYTE *buf = NULL;
4901 DWORD size = 0;
4902
4903 /* Test with empty id */
4904 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4905 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4906 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4907 if (buf)
4908 {
4909 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4910 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4911 LocalFree(buf);
4912 }
4913 /* With just a key id */
4914 info.KeyId.cbData = sizeof(keyId);
4915 info.KeyId.pbData = keyId;
4916 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4917 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4918 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4919 if (buf)
4920 {
4921 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4922 size);
4923 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4924 LocalFree(buf);
4925 }
4926 /* With a bogus issuer name */
4927 info.KeyId.cbData = 0;
4928 info.AuthorityCertIssuer.cAltEntry = 1;
4929 info.AuthorityCertIssuer.rgAltEntry = &entry;
4930 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4931 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4932 ok(!ret && GetLastError() == E_INVALIDARG,
4933 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4934 /* With an issuer name */
4935 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4936 U(entry).pwszURL = (LPWSTR)url;
4937 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4938 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4939 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4940 if (buf)
4941 {
4942 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4943 size);
4944 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4945 "Unexpected value\n");
4946 LocalFree(buf);
4947 }
4948 /* With just a serial number */
4949 info.AuthorityCertIssuer.cAltEntry = 0;
4950 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4951 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4952 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4953 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4954 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4955 if (buf)
4956 {
4957 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4958 size);
4959 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4960 LocalFree(buf);
4961 }
4962 }
4963
4964 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4965 {
4966 BOOL ret;
4967 LPBYTE buf = NULL;
4968 DWORD size = 0;
4969
4970 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4971 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4972 &buf, &size);
4973 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4974 if (buf)
4975 {
4976 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4977
4978 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4979 size);
4980 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4981 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4982 "Expected no issuer name entries\n");
4983 ok(info->AuthorityCertSerialNumber.cbData == 0,
4984 "Expected no serial number\n");
4985 LocalFree(buf);
4986 }
4987 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4988 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4989 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4990 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4991 if (buf)
4992 {
4993 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4994
4995 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4996 size);
4997 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4998 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4999 "Unexpected key id\n");
5000 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5001 "Expected no issuer name entries\n");
5002 ok(info->AuthorityCertSerialNumber.cbData == 0,
5003 "Expected no serial number\n");
5004 LocalFree(buf);
5005 }
5006 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5007 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5008 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5009 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5010 if (buf)
5011 {
5012 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5013
5014 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5015 size);
5016 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5017 ok(info->AuthorityCertIssuer.cAltEntry == 1,
5018 "Expected 1 issuer entry, got %d\n",
5019 info->AuthorityCertIssuer.cAltEntry);
5020 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5021 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5022 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5023 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5024 url), "Unexpected URL\n");
5025 ok(info->AuthorityCertSerialNumber.cbData == 0,
5026 "Expected no serial number\n");
5027 LocalFree(buf);
5028 }
5029 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5030 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5031 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5032 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5033 if (buf)
5034 {
5035 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5036
5037 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5038 size);
5039 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5040 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5041 "Expected no issuer name entries\n");
5042 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5043 "Unexpected serial number len\n");
5044 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5045 sizeof(serialNum)), "Unexpected serial number\n");
5046 LocalFree(buf);
5047 }
5048 }
5049
5050 static const BYTE authorityInfoAccessWithUrl[] = {
5051 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5052 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5053 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5054 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5055 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5056 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5057
5058 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5059 {
5060 static char oid1[] = "1.2.3";
5061 static char oid2[] = "1.5.6";
5062 BOOL ret;
5063 BYTE *buf = NULL;
5064 DWORD size = 0;
5065 CERT_ACCESS_DESCRIPTION accessDescription[2];
5066 CERT_AUTHORITY_INFO_ACCESS aia;
5067
5068 memset(accessDescription, 0, sizeof(accessDescription));
5069 aia.cAccDescr = 0;
5070 aia.rgAccDescr = NULL;
5071 /* Having no access descriptions is allowed */
5072 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5073 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5074 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5075 if (buf)
5076 {
5077 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5078 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5079 LocalFree(buf);
5080 buf = NULL;
5081 }
5082 /* It can't have an empty access method */
5083 aia.cAccDescr = 1;
5084 aia.rgAccDescr = accessDescription;
5085 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5086 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5087 ok(!ret && (GetLastError() == E_INVALIDARG ||
5088 GetLastError() == OSS_LIMITED /* Win9x */),
5089 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5090 /* It can't have an empty location */
5091 accessDescription[0].pszAccessMethod = oid1;
5092 SetLastError(0xdeadbeef);
5093 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5094 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5095 ok(!ret && GetLastError() == E_INVALIDARG,
5096 "expected E_INVALIDARG, got %08x\n", GetLastError());
5097 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5098 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5099 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5100 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5101 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5102 if (buf)
5103 {
5104 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5105 size);
5106 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5107 "unexpected value\n");
5108 LocalFree(buf);
5109 buf = NULL;
5110 }
5111 accessDescription[1].pszAccessMethod = oid2;
5112 accessDescription[1].AccessLocation.dwAltNameChoice =
5113 CERT_ALT_NAME_IP_ADDRESS;
5114 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5115 sizeof(encodedIPAddr);
5116 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5117 (LPBYTE)encodedIPAddr;
5118 aia.cAccDescr = 2;
5119 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5120 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5121 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5122 if (buf)
5123 {
5124 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5125 "unexpected size %d\n", size);
5126 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5127 "unexpected value\n");
5128 LocalFree(buf);
5129 buf = NULL;
5130 }
5131 }
5132
5133 static void compareAuthorityInfoAccess(LPCSTR header,
5134 const CERT_AUTHORITY_INFO_ACCESS *expected,
5135 const CERT_AUTHORITY_INFO_ACCESS *got)
5136 {
5137 DWORD i;
5138
5139 ok(expected->cAccDescr == got->cAccDescr,
5140 "%s: expected %d access descriptions, got %d\n", header,
5141 expected->cAccDescr, got->cAccDescr);
5142 for (i = 0; i < expected->cAccDescr; i++)
5143 {
5144 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5145 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5146 header, i, expected->rgAccDescr[i].pszAccessMethod,
5147 got->rgAccDescr[i].pszAccessMethod);
5148 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5149 &got->rgAccDescr[i].AccessLocation);
5150 }
5151 }
5152
5153 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5154 {
5155 static char oid1[] = "1.2.3";
5156 static char oid2[] = "1.5.6";
5157 BOOL ret;
5158 LPBYTE buf = NULL;
5159 DWORD size = 0;
5160
5161 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5162 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5163 &buf, &size);
5164 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5165 if (buf)
5166 {
5167 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5168
5169 compareAuthorityInfoAccess("empty AIA", &aia,
5170 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5171 LocalFree(buf);
5172 buf = NULL;
5173 }
5174 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5175 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5176 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5177 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5178 if (buf)
5179 {
5180 CERT_ACCESS_DESCRIPTION accessDescription;
5181 CERT_AUTHORITY_INFO_ACCESS aia;
5182
5183 accessDescription.pszAccessMethod = oid1;
5184 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5185 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5186 aia.cAccDescr = 1;
5187 aia.rgAccDescr = &accessDescription;
5188 compareAuthorityInfoAccess("AIA with URL", &aia,
5189 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5190 LocalFree(buf);
5191 buf = NULL;
5192 }
5193 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5194 authorityInfoAccessWithUrlAndIPAddr,
5195 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5196 NULL, &buf, &size);
5197 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5198 if (buf)
5199 {
5200 CERT_ACCESS_DESCRIPTION accessDescription[2];
5201 CERT_AUTHORITY_INFO_ACCESS aia;
5202
5203 accessDescription[0].pszAccessMethod = oid1;
5204 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5205 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5206 accessDescription[1].pszAccessMethod = oid2;
5207 accessDescription[1].AccessLocation.dwAltNameChoice =
5208 CERT_ALT_NAME_IP_ADDRESS;
5209 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5210 sizeof(encodedIPAddr);
5211 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5212 (LPBYTE)encodedIPAddr;
5213 aia.cAccDescr = 2;
5214 aia.rgAccDescr = accessDescription;
5215 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5216 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5217 LocalFree(buf);
5218 buf = NULL;
5219 }
5220 }
5221
5222 static const BYTE emptyCTL[] = {
5223 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5224 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5225 static const BYTE emptyCTLWithVersion1[] = {
5226 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5227 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5228 static const BYTE ctlWithUsageIdentifier[] = {
5229 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5230 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5231 static const BYTE ctlWithListIdentifier[] = {
5232 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5233 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5234 static const BYTE ctlWithSequenceNumber[] = {
5235 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5236 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5237 static const BYTE ctlWithThisUpdate[] = {
5238 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5239 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5240 static const BYTE ctlWithThisAndNextUpdate[] = {
5241 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5242 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5243 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5244 static const BYTE ctlWithAlgId[] = {
5245 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5246 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5247 static const BYTE ctlWithBogusEntry[] = {
5248 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5249 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5250 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5251 static const BYTE ctlWithOneEntry[] = {
5252 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5253 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5254 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5255 static const BYTE ctlWithTwoEntries[] = {
5256 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5257 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5258 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5259 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5260 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5261
5262 static void test_encodeCTL(DWORD dwEncoding)
5263 {
5264 static char oid1[] = "1.2.3";
5265 static char oid2[] = "1.5.6";
5266 char *pOid1 = oid1;
5267 BOOL ret;
5268 BYTE *buf = NULL;
5269 DWORD size = 0;
5270 CTL_INFO info;
5271 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5272 CTL_ENTRY ctlEntry[2];
5273 CRYPT_ATTRIBUTE attr1, attr2;
5274 CRYPT_ATTR_BLOB value1, value2;
5275
5276 memset(&info, 0, sizeof(info));
5277 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5278 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5279 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5280 if (buf)
5281 {
5282 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5283 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5284 LocalFree(buf);
5285 buf = NULL;
5286 }
5287 info.dwVersion = 1;
5288 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5289 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5290 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5291 if (buf)
5292 {
5293 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5294 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5295 LocalFree(buf);
5296 buf = NULL;
5297 }
5298 info.dwVersion = 0;
5299 info.SubjectUsage.cUsageIdentifier = 1;
5300 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5301 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5302 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5303 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5304 if (buf)
5305 {
5306 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5307 size);
5308 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5309 LocalFree(buf);
5310 buf = NULL;
5311 }
5312 info.SubjectUsage.cUsageIdentifier = 0;
5313 info.ListIdentifier.cbData = sizeof(serialNum);
5314 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5315 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5316 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5317 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5318 if (buf)
5319 {
5320 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5321 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5322 LocalFree(buf);
5323 buf = NULL;
5324 }
5325 info.ListIdentifier.cbData = 0;
5326 info.SequenceNumber.cbData = sizeof(serialNum);
5327 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5328 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5329 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5330 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5331 if (buf)
5332 {
5333 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5334 size);
5335 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5336 LocalFree(buf);
5337 buf = NULL;
5338 }
5339 info.SequenceNumber.cbData = 0;
5340 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5341 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5342 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5343 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5344 if (buf)
5345 {
5346 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5347 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5348 LocalFree(buf);
5349 buf = NULL;
5350 }
5351 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5352 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5353 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5354 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5355 if (buf)
5356 {
5357 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5358 size);
5359 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5360 LocalFree(buf);
5361 buf = NULL;
5362 }
5363 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5364 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5365 info.SubjectAlgorithm.pszObjId = oid2;
5366 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5367 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5368 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5369 if (buf)
5370 {
5371 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5372 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5373 LocalFree(buf);
5374 buf = NULL;
5375 }
5376 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5377 * (see tests below) but it'll encode fine.
5378 */
5379 info.SubjectAlgorithm.pszObjId = NULL;
5380 value1.cbData = sizeof(serialNum);
5381 value1.pbData = (LPBYTE)serialNum;
5382 attr1.pszObjId = oid1;
5383 attr1.cValue = 1;
5384 attr1.rgValue = &value1;
5385 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5386 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5387 ctlEntry[0].cAttribute = 1;
5388 ctlEntry[0].rgAttribute = &attr1;
5389 info.cCTLEntry = 1;
5390 info.rgCTLEntry = ctlEntry;
5391 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5392 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5393 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5394 if (buf)
5395 {
5396 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5397 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5398 LocalFree(buf);
5399 buf = NULL;
5400 }
5401 value1.cbData = sizeof(emptySequence);
5402 value1.pbData = (LPBYTE)emptySequence;
5403 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5404 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5405 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5406 if (buf)
5407 {
5408 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5409 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5410 LocalFree(buf);
5411 buf = NULL;
5412 }
5413 value2.cbData = sizeof(encodedIPAddr);
5414 value2.pbData = (LPBYTE)encodedIPAddr;
5415 attr2.pszObjId = oid2;
5416 attr2.cValue = 1;
5417 attr2.rgValue = &value2;
5418 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5419 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5420 ctlEntry[1].cAttribute = 1;
5421 ctlEntry[1].rgAttribute = &attr2;
5422 info.cCTLEntry = 2;
5423 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5424 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5425 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5426 if (buf)
5427 {
5428 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5429 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5430 LocalFree(buf);
5431 buf = NULL;
5432 }
5433 }
5434
5435 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5436 const CTL_INFO *got)
5437 {
5438 DWORD i, j, k;
5439
5440 ok(expected->dwVersion == got->dwVersion,
5441 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5442 got->dwVersion);
5443 ok(expected->SubjectUsage.cUsageIdentifier ==
5444 got->SubjectUsage.cUsageIdentifier,
5445 "%s: expected %d usage identifiers, got %d\n", header,
5446 expected->SubjectUsage.cUsageIdentifier,
5447 got->SubjectUsage.cUsageIdentifier);
5448 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5449 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5450 got->SubjectUsage.rgpszUsageIdentifier[i]),
5451 "%s[%d]: expected %s, got %s\n", header, i,
5452 expected->SubjectUsage.rgpszUsageIdentifier[i],
5453 got->SubjectUsage.rgpszUsageIdentifier[i]);
5454 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5455 "%s: expected list identifier of %d bytes, got %d\n", header,
5456 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5457 if (expected->ListIdentifier.cbData)
5458 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5459 expected->ListIdentifier.cbData),
5460 "%s: unexpected list identifier value\n", header);
5461 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5462 "%s: expected sequence number of %d bytes, got %d\n", header,
5463 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5464 if (expected->SequenceNumber.cbData)
5465 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5466 expected->SequenceNumber.cbData),
5467 "%s: unexpected sequence number value\n", header);
5468 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5469 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5470 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5471 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5472 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5473 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5474 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5475 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5476 if (expected->SubjectAlgorithm.pszObjId &&
5477 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5478 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5479 expected->SubjectAlgorithm.pszObjId);
5480 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5481 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5482 got->SubjectAlgorithm.pszObjId),
5483 "%s: expected subject algorithm %s, got %s\n", header,
5484 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5485 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5486 got->SubjectAlgorithm.Parameters.cbData,
5487 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5488 expected->SubjectAlgorithm.Parameters.cbData,
5489 got->SubjectAlgorithm.Parameters.cbData);
5490 if (expected->SubjectAlgorithm.Parameters.cbData)
5491 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5492 got->SubjectAlgorithm.Parameters.pbData,
5493 expected->SubjectAlgorithm.Parameters.cbData),
5494 "%s: unexpected subject algorithm parameter value\n", header);
5495 ok(expected->cCTLEntry == got->cCTLEntry,
5496 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5497 got->cCTLEntry);
5498 for (i = 0; i < expected->cCTLEntry; i++)
5499 {
5500 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5501 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5502 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5503 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5504 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5505 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5506 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5507 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5508 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5509 "%s[%d]: unexpected subject identifier value\n",
5510 header, i);
5511 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5512 {
5513 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5514 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5515 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5516 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5517 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5518 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5519 {
5520 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5521 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5522 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5523 header, i, j, k,
5524 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5525 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5526 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5527 ok(!memcmp(
5528 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5529 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5530 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5531 "%s[%d][%d][%d]: unexpected value\n",
5532 header, i, j, k);
5533 }
5534 }
5535 }
5536 ok(expected->cExtension == got->cExtension,
5537 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5538 got->cExtension);
5539 for (i = 0; i < expected->cExtension; i++)
5540 {
5541 ok(!strcmp(expected->rgExtension[i].pszObjId,
5542 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5543 header, i, expected->rgExtension[i].pszObjId,
5544 got->rgExtension[i].pszObjId);
5545 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5546 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5547 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5548 ok(expected->rgExtension[i].Value.cbData ==
5549 got->rgExtension[i].Value.cbData,
5550 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5551 header, i, expected->rgExtension[i].Value.cbData,
5552 got->rgExtension[i].Value.cbData);
5553 if (expected->rgExtension[i].Value.cbData)
5554 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5555 got->rgExtension[i].Value.pbData,
5556 expected->rgExtension[i].Value.cbData),
5557 "%s[%d]: unexpected extension value\n", header, i);
5558 }
5559 }
5560
5561 static const BYTE signedCTL[] = {
5562 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5563 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5564 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5565 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5566 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5567 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5568 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5569 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5570 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5571 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5572 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5573 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5574 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5575 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5576 static const BYTE signedCTLWithCTLInnerContent[] = {
5577 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5578 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5579 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5580 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5581 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5582 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5583 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5584 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5585 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5586 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5587 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5588 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5589 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5590 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5591 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5592 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5593 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5594 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5595 0x57,0x6c,0x0b,0x47,0xb8 };
5596
5597 static void test_decodeCTL(DWORD dwEncoding)
5598 {
5599 static char oid1[] = "1.2.3";
5600 static char oid2[] = "1.5.6";
5601 static BYTE nullData[] = { 5,0 };
5602 char *pOid1 = oid1;
5603 BOOL ret;
5604 BYTE *buf = NULL;
5605 DWORD size = 0;
5606 CTL_INFO info;
5607 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5608 CTL_ENTRY ctlEntry[2];
5609 CRYPT_ATTRIBUTE attr1, attr2;
5610 CRYPT_ATTR_BLOB value1, value2;
5611
5612 memset(&info, 0, sizeof(info));
5613 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5614 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5615 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5616 if (buf)
5617 {
5618 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5619 LocalFree(buf);
5620 buf = NULL;
5621 }
5622 info.dwVersion = 1;
5623 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5624 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5625 &size);
5626 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5627 if (buf)
5628 {
5629 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5630 LocalFree(buf);
5631 buf = NULL;
5632 }
5633 info.dwVersion = 0;
5634 info.SubjectUsage.cUsageIdentifier = 1;
5635 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5636 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5637 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5638 &buf, &size);
5639 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5640 if (buf)
5641 {
5642 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5643 LocalFree(buf);
5644 buf = NULL;
5645 }
5646 info.SubjectUsage.cUsageIdentifier = 0;
5647 info.ListIdentifier.cbData = sizeof(serialNum);
5648 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5649 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5650 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5651 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5652 if (buf)
5653 {
5654 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5655 LocalFree(buf);
5656 buf = NULL;
5657 }
5658 info.ListIdentifier.cbData = 0;
5659 info.SequenceNumber.cbData = sizeof(serialNum);
5660 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5661 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5662 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5663 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5664 if (buf)
5665 {
5666 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5667 LocalFree(buf);
5668 buf = NULL;
5669 }
5670 info.SequenceNumber.cbData = 0;
5671 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5672 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5673 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5674 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5675 if (buf)
5676 {
5677 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5678 LocalFree(buf);
5679 buf = NULL;
5680 }
5681 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5682 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5683 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5684 &buf, &size);
5685 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5686 if (buf)
5687 {
5688 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5689 LocalFree(buf);
5690 buf = NULL;
5691 }
5692 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5693 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5694 info.SubjectAlgorithm.pszObjId = oid2;
5695 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5696 info.SubjectAlgorithm.Parameters.pbData = nullData;
5697 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5698 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5699 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5700 if (buf)
5701 {
5702 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5703 LocalFree(buf);
5704 buf = NULL;
5705 }
5706 SetLastError(0xdeadbeef);
5707 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5708 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5709 ok(!ret &&
5710 (GetLastError() == CRYPT_E_ASN1_EOD ||
5711 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5712 GetLastError() == OSS_MORE_INPUT), /* Win9x */
5713 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5714 GetLastError());
5715 info.SubjectAlgorithm.Parameters.cbData = 0;
5716 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5717 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5718 info.SubjectAlgorithm.pszObjId = oid2;
5719 info.SubjectAlgorithm.pszObjId = NULL;
5720 value1.cbData = sizeof(emptySequence);
5721 value1.pbData = (LPBYTE)emptySequence;
5722 attr1.pszObjId = oid1;
5723 attr1.cValue = 1;
5724 attr1.rgValue = &value1;
5725 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5726 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5727 ctlEntry[0].cAttribute = 1;
5728 ctlEntry[0].rgAttribute = &attr1;
5729 info.cCTLEntry = 1;
5730 info.rgCTLEntry = ctlEntry;
5731 SetLastError(0xdeadbeef);
5732 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5733 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5734 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5735 if (buf)
5736 {
5737 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5738 LocalFree(buf);
5739 buf = NULL;
5740 }
5741 value2.cbData = sizeof(encodedIPAddr);
5742 value2.pbData = (LPBYTE)encodedIPAddr;
5743 attr2.pszObjId = oid2;
5744 attr2.cValue = 1;
5745 attr2.rgValue = &value2;
5746 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5747 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5748 ctlEntry[1].cAttribute = 1;
5749 ctlEntry[1].rgAttribute = &attr2;
5750 info.cCTLEntry = 2;
5751 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5752 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5753 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5754 if (buf)
5755 {
5756 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5757 LocalFree(buf);
5758 buf = NULL;
5759 }
5760 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5761 SetLastError(0xdeadbeef);
5762 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5763 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5764 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5765 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5766 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5767 GetLastError());
5768 SetLastError(0xdeadbeef);
5769 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5770 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5771 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5772 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5773 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5774 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5775 GetLastError());
5776 }
5777
5778 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5779 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5780 0x03,0,0,0,0,0,0 };
5781 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5782 0xa0,0x01,0x01 };
5783 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5784 0x03,0x02,0x01,0x01 };
5785 static BYTE bogusDER[] = { 1 };
5786
5787 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5788 {
5789 BOOL ret;
5790 BYTE *buf = NULL;
5791 DWORD size = 0;
5792 CRYPT_CONTENT_INFO info = { 0 };
5793 char oid1[] = "1.2.3";
5794
5795 if (0)
5796 {
5797 /* Crashes on win9x */
5798 SetLastError(0xdeadbeef);
5799 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5800 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5801 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5802 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5803 }
5804 SetLastError(0xdeadbeef);
5805 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5806 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5807 ok(!ret && (GetLastError() == E_INVALIDARG ||
5808 GetLastError() == OSS_LIMITED /* Win9x */),
5809 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5810 info.pszObjId = oid1;
5811 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5812 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5813 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5814 if (buf)
5815 {
5816 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5817 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5818 LocalFree(buf);
5819 }
5820 info.Content.pbData = bogusDER;
5821 info.Content.cbData = sizeof(bogusDER);
5822 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5823 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5824 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5825 if (buf)
5826 {
5827 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5828 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5829 LocalFree(buf);
5830 }
5831 info.Content.pbData = (BYTE *)ints[0].encoded;
5832 info.Content.cbData = ints[0].encoded[1] + 2;
5833 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5834 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5835 if (buf)
5836 {
5837 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5838 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5839 LocalFree(buf);
5840 }
5841 }
5842
5843 static const BYTE indefiniteSignedPKCSContent[] = {
5844 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5845 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5846 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5847 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5848 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5849 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5850 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5851 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5852 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5853 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5854 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5855 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5856 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5857 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5858 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5859 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5860 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5861 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5862 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5863 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5864 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5865 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5866 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5867 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5868 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5869 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5870 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5871 0x00,0x00,0x00,0x00,0x00,0x00 };
5872
5873 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5874 {
5875 BOOL ret;
5876 LPBYTE buf = NULL;
5877 DWORD size = 0;
5878 CRYPT_CONTENT_INFO *info;
5879
5880 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5881 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5882 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5883 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5884 if (buf)
5885 {
5886 info = (CRYPT_CONTENT_INFO *)buf;
5887
5888 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5889 info->pszObjId);
5890 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5891 info->Content.cbData);
5892 LocalFree(buf);
5893 }
5894 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5895 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5896 0, NULL, NULL, &size);
5897 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5898 SetLastError(0xdeadbeef);
5899 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5900 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5901 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5902 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5903 * I doubt an app depends on that.
5904 */
5905 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5906 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5907 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5908 GetLastError());
5909 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5910 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5911 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5912 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5913 if (buf)
5914 {
5915 info = (CRYPT_CONTENT_INFO *)buf;
5916
5917 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5918 info->pszObjId);
5919 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5920 "Unexpected size %d\n", info->Content.cbData);
5921 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5922 info->Content.cbData), "Unexpected value\n");
5923 LocalFree(buf);
5924 }
5925 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5926 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5927 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5928 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5929 if (buf)
5930 {
5931 info = (CRYPT_CONTENT_INFO *)buf;
5932
5933 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5934 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5935 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5936 info->Content.cbData);
5937 LocalFree(buf);
5938 }
5939 }
5940
5941 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5942 0x00 };
5943 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5944 0x01 };
5945 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5946 0x02,0x01,0x01 };
5947
5948 static void test_encodePKCSAttribute(DWORD dwEncoding)
5949 {
5950 CRYPT_ATTRIBUTE attr = { 0 };
5951 BOOL ret;
5952 LPBYTE buf = NULL;
5953 DWORD size = 0;
5954 CRYPT_ATTR_BLOB blob;
5955 char oid[] = "1.2.3";
5956
5957 if (0)
5958 {
5959 /* Crashes on win9x */
5960 SetLastError(0xdeadbeef);
5961 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5962 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5963 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5964 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5965 }
5966 SetLastError(0xdeadbeef);
5967 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5968 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5969 ok(!ret && (GetLastError() == E_INVALIDARG ||
5970 GetLastError() == OSS_LIMITED /* Win9x */),
5971 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5972 attr.pszObjId = oid;
5973 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5974 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5975 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5976 if (buf)
5977 {
5978 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5979 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5980 LocalFree(buf);
5981 }
5982 blob.cbData = sizeof(bogusDER);
5983 blob.pbData = bogusDER;
5984 attr.cValue = 1;
5985 attr.rgValue = &blob;
5986 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5987 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5988 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5989 if (buf)
5990 {
5991 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5992 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5993 LocalFree(buf);
5994 }
5995 blob.pbData = (BYTE *)ints[0].encoded;
5996 blob.cbData = ints[0].encoded[1] + 2;
5997 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5998 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5999 if (buf)
6000 {
6001 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6002 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6003 LocalFree(buf);
6004 }
6005 }
6006
6007 static void test_decodePKCSAttribute(DWORD dwEncoding)
6008 {
6009 BOOL ret;
6010 LPBYTE buf = NULL;
6011 DWORD size = 0;
6012 CRYPT_ATTRIBUTE *attr;
6013
6014 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6015 emptyPKCSAttr, sizeof(emptyPKCSAttr),
6016 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6017 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6018 if (buf)
6019 {
6020 attr = (CRYPT_ATTRIBUTE *)buf;
6021
6022 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6023 attr->pszObjId);
6024 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6025 LocalFree(buf);
6026 }
6027 SetLastError(0xdeadbeef);
6028 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6029 bogusPKCSAttr, sizeof(bogusPKCSAttr),
6030 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6031 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6032 * I doubt an app depends on that.
6033 */
6034 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6035 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6036 GetLastError() == OSS_MORE_INPUT /* Win9x */),
6037 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6038 GetLastError());
6039 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6040 intPKCSAttr, sizeof(intPKCSAttr),
6041 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6042 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6043 if (buf)
6044 {
6045 attr = (CRYPT_ATTRIBUTE *)buf;
6046
6047 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6048 attr->pszObjId);
6049 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6050 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6051 "Unexpected size %d\n", attr->rgValue[0].cbData);
6052 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6053 attr->rgValue[0].cbData), "Unexpected value\n");
6054 LocalFree(buf);
6055 }
6056 }
6057
6058 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6059 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6060 0x2a,0x03,0x31,0x00 };
6061 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6062 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6063
6064 static void test_encodePKCSAttributes(DWORD dwEncoding)
6065 {
6066 CRYPT_ATTRIBUTES attributes = { 0 };
6067 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6068 CRYPT_ATTR_BLOB blob;
6069 BOOL ret;
6070 LPBYTE buf = NULL;
6071 DWORD size = 0;
6072 char oid1[] = "1.2.3", oid2[] = "1.5.6";
6073
6074 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6075 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6076 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6077 if (buf)
6078 {
6079 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6080 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6081 LocalFree(buf);
6082 }
6083 attributes.cAttr = 1;
6084 attributes.rgAttr = attr;
6085 SetLastError(0xdeadbeef);
6086 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6087 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6088 ok(!ret && (GetLastError() == E_INVALIDARG ||
6089 GetLastError() == OSS_LIMITED /* Win9x */),
6090 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6091 attr[0].pszObjId = oid1;
6092 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6093 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6094 if (buf)
6095 {
6096 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6097 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6098 LocalFree(buf);
6099 }
6100 attr[1].pszObjId = oid2;
6101 attr[1].cValue = 1;
6102 attr[1].rgValue = &blob;
6103 blob.pbData = (BYTE *)ints[0].encoded;
6104 blob.cbData = ints[0].encoded[1] + 2;
6105 attributes.cAttr = 2;
6106 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6107 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6108 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6109 if (buf)
6110 {
6111 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6112 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6113 LocalFree(buf);
6114 }
6115 }
6116
6117 static void test_decodePKCSAttributes(DWORD dwEncoding)
6118 {
6119 BOOL ret;
6120 LPBYTE buf = NULL;
6121 DWORD size = 0;
6122 CRYPT_ATTRIBUTES *attributes;
6123
6124 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6125 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6126 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6127 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6128 if (buf)
6129 {
6130 attributes = (CRYPT_ATTRIBUTES *)buf;
6131 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6132 attributes->cAttr);
6133 LocalFree(buf);
6134 }
6135 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6136 singlePKCSAttributes, sizeof(singlePKCSAttributes),
6137 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6138 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6139 if (buf)
6140 {
6141 attributes = (CRYPT_ATTRIBUTES *)buf;
6142 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6143 attributes->cAttr);
6144 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6145 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6146 ok(attributes->rgAttr[0].cValue == 0,
6147 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6148 LocalFree(buf);
6149 }
6150 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6151 doublePKCSAttributes, sizeof(doublePKCSAttributes),
6152 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6153 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6154 if (buf)
6155 {
6156 attributes = (CRYPT_ATTRIBUTES *)buf;
6157 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6158 attributes->cAttr);
6159 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6160 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6161 ok(attributes->rgAttr[0].cValue == 0,
6162 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6163 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6164 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6165 ok(attributes->rgAttr[1].cValue == 1,
6166 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6167 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6168 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6169 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6170 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6171 LocalFree(buf);
6172 }
6173 }
6174
6175 static const BYTE singleCapability[] = {
6176 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6177 static const BYTE twoCapabilities[] = {
6178 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6179 static const BYTE singleCapabilitywithNULL[] = {
6180 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6181
6182 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6183 {
6184 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6185 BOOL ret;
6186 LPBYTE buf = NULL;
6187 DWORD size = 0;
6188 CRYPT_SMIME_CAPABILITY capability[2];
6189 CRYPT_SMIME_CAPABILITIES capabilities;
6190
6191 /* An empty capabilities is allowed */
6192 capabilities.cCapability = 0;
6193 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6194 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6195 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6196 if (buf)
6197 {
6198 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6199 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6200 LocalFree(buf);
6201 }
6202 /* A non-empty capabilities with an empty capability (lacking an OID) is
6203 * not allowed
6204 */
6205 capability[0].pszObjId = NULL;
6206 capability[0].Parameters.cbData = 0;
6207 capabilities.cCapability = 1;
6208 capabilities.rgCapability = capability;
6209 SetLastError(0xdeadbeef);
6210 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6211 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6212 ok(!ret && (GetLastError() == E_INVALIDARG ||
6213 GetLastError() == OSS_LIMITED /* Win9x */),
6214 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6215 capability[0].pszObjId = oid1;
6216 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6217 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6218 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6219 if (buf)
6220 {
6221 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6222 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6223 LocalFree(buf);
6224 }
6225 capability[1].pszObjId = oid2;
6226 capability[1].Parameters.cbData = 0;
6227 capabilities.cCapability = 2;
6228 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6229 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6230 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6231 if (buf)
6232 {
6233 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6234 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6235 LocalFree(buf);
6236 }
6237 }
6238
6239 static void compareSMimeCapabilities(LPCSTR header,
6240 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6241 {
6242 DWORD i;
6243
6244 ok(got->cCapability == expected->cCapability,
6245 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6246 got->cCapability);
6247 for (i = 0; i < expected->cCapability; i++)
6248 {
6249 ok(!strcmp(expected->rgCapability[i].pszObjId,
6250 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6251 header, i, expected->rgCapability[i].pszObjId,
6252 got->rgCapability[i].pszObjId);
6253 ok(expected->rgCapability[i].Parameters.cbData ==
6254 got->rgCapability[i].Parameters.cbData,
6255 "%s[%d]: expected %d bytes, got %d\n", header, i,
6256 expected->rgCapability[i].Parameters.cbData,
6257 got->rgCapability[i].Parameters.cbData);
6258 if (expected->rgCapability[i].Parameters.cbData)
6259 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6260 got->rgCapability[i].Parameters.pbData,
6261 expected->rgCapability[i].Parameters.cbData),
6262 "%s[%d]: unexpected value\n", header, i);
6263 }
6264 }
6265
6266 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6267 {
6268 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6269 BOOL ret;
6270 DWORD size = 0;
6271 CRYPT_SMIME_CAPABILITY capability[2];
6272 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6273
6274 SetLastError(0xdeadbeef);
6275 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6276 emptySequence, sizeof(emptySequence),
6277 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6278 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6279 if (ret)
6280 {
6281 capabilities.cCapability = 0;
6282 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6283 LocalFree(ptr);
6284 }
6285 SetLastError(0xdeadbeef);
6286 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6287 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6288 &ptr, &size);
6289 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6290 if (ret)
6291 {
6292 capability[0].pszObjId = oid1;
6293 capability[0].Parameters.cbData = 0;
6294 capabilities.cCapability = 1;
6295 capabilities.rgCapability = capability;
6296 compareSMimeCapabilities("single capability", &capabilities, ptr);
6297 LocalFree(ptr);
6298 }
6299 SetLastError(0xdeadbeef);
6300 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6301 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6302 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6303 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6304 if (ret)
6305 {
6306 BYTE NULLparam[] = {0x05, 0x00};
6307 capability[0].pszObjId = oid1;
6308 capability[0].Parameters.cbData = 2;
6309 capability[0].Parameters.pbData = NULLparam;
6310 capabilities.cCapability = 1;
6311 capabilities.rgCapability = capability;
6312 compareSMimeCapabilities("single capability with NULL", &capabilities,
6313 ptr);
6314 LocalFree(ptr);
6315 }
6316 SetLastError(0xdeadbeef);
6317 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6318 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6319 &ptr, &size);
6320 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6321 if (ret)
6322 {
6323 capability[0].Parameters.cbData = 0;
6324 capability[1].pszObjId = oid2;
6325 capability[1].Parameters.cbData = 0;
6326 capabilities.cCapability = 2;
6327 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6328 LocalFree(ptr);
6329 }
6330 }
6331
6332 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6333 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6334 0x67 };
6335 static const BYTE minimalPKCSSigner[] = {
6336 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6337 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6338 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6339 static const BYTE PKCSSignerWithSerial[] = {
6340 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6341 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6342 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6343 0x00 };
6344 static const BYTE PKCSSignerWithHashAlgo[] = {
6345 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6346 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6347 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6348 0x00,0x04,0x00 };
6349 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6350 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6351 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6352 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6353 0x06,0x05,0x00,0x04,0x00 };
6354 static const BYTE PKCSSignerWithHash[] = {
6355 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6356 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6357 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6358 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6359 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6360 static const BYTE PKCSSignerWithAuthAttr[] = {
6361 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6362 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6363 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6364 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6365 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6366 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6367 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6368
6369 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6370 {
6371 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6372 BOOL ret;
6373 LPBYTE buf = NULL;
6374 DWORD size = 0;
6375 CMSG_SIGNER_INFO info = { 0 };
6376 char oid_common_name[] = szOID_COMMON_NAME;
6377 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6378 (LPBYTE)encodedCommonName };
6379 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6380
6381 SetLastError(0xdeadbeef);
6382 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6383 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6384 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6385 {
6386 skip("no PKCS7_SIGNER_INFO encode support\n");
6387 return;
6388 }
6389 ok(!ret && (GetLastError() == E_INVALIDARG ||
6390 GetLastError() == OSS_LIMITED /* Win9x */),
6391 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6392 /* To be encoded, a signer must have an issuer at least, and the encoding
6393 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6394 * see decoding tests.)
6395 */
6396 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6397 info.Issuer.pbData = encodedCommonNameNoNull;
6398 SetLastError(0xdeadbeef);
6399 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6400 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6401 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6402 ok(!ret && GetLastError() == E_INVALIDARG,
6403 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6404 else
6405 {
6406 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6407 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6408 if (buf)
6409 {
6410 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6411 if (size == sizeof(minimalPKCSSigner))
6412 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6413 else
6414 ok(0, "Unexpected value\n");
6415 LocalFree(buf);
6416 }
6417 }
6418 info.SerialNumber.cbData = sizeof(serialNum);
6419 info.SerialNumber.pbData = (BYTE *)serialNum;
6420 SetLastError(0xdeadbeef);
6421 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6422 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6423 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6424 ok(!ret && GetLastError() == E_INVALIDARG,
6425 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6426 else
6427 {
6428 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6429 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6430 if (buf)
6431 {
6432 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6433 size);
6434 if (size == sizeof(PKCSSignerWithSerial))
6435 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6436 "Unexpected value\n");
6437 else
6438 ok(0, "Unexpected value\n");
6439 LocalFree(buf);
6440 }
6441 }
6442 info.HashAlgorithm.pszObjId = oid1;
6443 SetLastError(0xdeadbeef);
6444 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6445 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6446 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6447 ok(!ret && GetLastError() == E_INVALIDARG,
6448 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6449 else
6450 {
6451 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6452 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6453 if (buf)
6454 {
6455 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6456 size);
6457 if (size == sizeof(PKCSSignerWithHashAlgo))
6458 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6459 "Unexpected value\n");
6460 else
6461 ok(0, "Unexpected value\n");
6462 LocalFree(buf);
6463 }
6464 }
6465 info.HashEncryptionAlgorithm.pszObjId = oid2;
6466 SetLastError(0xdeadbeef);
6467 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6468 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6469 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6470 ok(!ret && GetLastError() == E_INVALIDARG,
6471 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6472 else
6473 {
6474 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6475 if (buf)
6476 {
6477 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6478 "Unexpected size %d\n", size);
6479 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6480 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6481 "Unexpected value\n");
6482 else
6483 ok(0, "Unexpected value\n");
6484 LocalFree(buf);
6485 }
6486 }
6487 info.EncryptedHash.cbData = sizeof(hash);
6488 info.EncryptedHash.pbData = (BYTE *)hash;
6489 SetLastError(0xdeadbeef);
6490 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6491 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6492 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6493 ok(!ret && GetLastError() == E_INVALIDARG,
6494 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6495 else
6496 {
6497 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6498 if (buf)
6499 {
6500 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6501 size);
6502 if (size == sizeof(PKCSSignerWithHash))
6503 ok(!memcmp(buf, PKCSSignerWithHash, size),
6504 "Unexpected value\n");
6505 else
6506 ok(0, "Unexpected value\n");
6507 LocalFree(buf);
6508 }
6509 }
6510 info.AuthAttrs.cAttr = 1;
6511 info.AuthAttrs.rgAttr = &attr;
6512 SetLastError(0xdeadbeef);
6513 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6514 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6515 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6516 ok(!ret && GetLastError() == E_INVALIDARG,
6517 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6518 else
6519 {
6520 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6521 if (buf)
6522 {
6523 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6524 size);
6525 if (size == sizeof(PKCSSignerWithAuthAttr))
6526 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6527 "Unexpected value\n");
6528 else
6529 ok(0, "Unexpected value\n");
6530 LocalFree(buf);
6531 }
6532 }
6533 }
6534
6535 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6536 {
6537 BOOL ret;
6538 LPBYTE buf = NULL;
6539 DWORD size = 0;
6540 CMSG_SIGNER_INFO *info;
6541
6542 /* A PKCS signer can't be decoded without a serial number. */
6543 SetLastError(0xdeadbeef);
6544 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6545 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6546 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6547 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6548 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6549 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6550 GetLastError());
6551 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6552 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6553 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6554 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6555 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6556 if (buf)
6557 {
6558 info = (CMSG_SIGNER_INFO *)buf;
6559 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6560 info->dwVersion);
6561 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6562 "Unexpected size %d\n", info->Issuer.cbData);
6563 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6564 info->Issuer.cbData), "Unexpected value\n");
6565 ok(info->SerialNumber.cbData == sizeof(serialNum),
6566 "Unexpected size %d\n", info->SerialNumber.cbData);
6567 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6568 "Unexpected value\n");
6569 LocalFree(buf);
6570 }
6571 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6572 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6573 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6574 if (buf)
6575 {
6576 info = (CMSG_SIGNER_INFO *)buf;
6577 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6578 info->dwVersion);
6579 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6580 "Unexpected size %d\n", info->Issuer.cbData);
6581 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6582 info->Issuer.cbData), "Unexpected value\n");
6583 ok(info->SerialNumber.cbData == sizeof(serialNum),
6584 "Unexpected size %d\n", info->SerialNumber.cbData);
6585 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6586 "Unexpected value\n");
6587 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6588 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6589 LocalFree(buf);
6590 }
6591 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6592 PKCSSignerWithHashAndEncryptionAlgo,
6593 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6594 NULL, &buf, &size);
6595 if (buf)
6596 {
6597 info = (CMSG_SIGNER_INFO *)buf;
6598 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6599 info->dwVersion);
6600 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6601 "Unexpected size %d\n", info->Issuer.cbData);
6602 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6603 info->Issuer.cbData), "Unexpected value\n");
6604 ok(info->SerialNumber.cbData == sizeof(serialNum),
6605 "Unexpected size %d\n", info->SerialNumber.cbData);
6606 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6607 "Unexpected value\n");
6608 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6609 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6610 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6611 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6612 LocalFree(buf);
6613 }
6614 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6615 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6616 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6617 if (buf)
6618 {
6619 info = (CMSG_SIGNER_INFO *)buf;
6620 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6621 info->dwVersion);
6622 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6623 "Unexpected size %d\n", info->Issuer.cbData);
6624 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6625 info->Issuer.cbData), "Unexpected value\n");
6626 ok(info->SerialNumber.cbData == sizeof(serialNum),
6627 "Unexpected size %d\n", info->SerialNumber.cbData);
6628 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6629 "Unexpected value\n");
6630 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6631 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6632 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6633 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6634 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6635 info->EncryptedHash.cbData);
6636 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6637 "Unexpected value\n");
6638 LocalFree(buf);
6639 }
6640 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6641 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6642 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6643 if (buf)
6644 {
6645 info = (CMSG_SIGNER_INFO *)buf;
6646 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6647 info->AuthAttrs.cAttr);
6648 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6649 "Expected %s, got %s\n", szOID_COMMON_NAME,
6650 info->AuthAttrs.rgAttr[0].pszObjId);
6651 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6652 info->AuthAttrs.rgAttr[0].cValue);
6653 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6654 sizeof(encodedCommonName), "Unexpected size %d\n",
6655 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6656 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6657 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6658 LocalFree(buf);
6659 }
6660 }
6661
6662 static const BYTE CMSSignerWithKeyId[] = {
6663 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6664 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6665
6666 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6667 {
6668 BOOL ret;
6669 LPBYTE buf = NULL;
6670 DWORD size = 0;
6671 CMSG_CMS_SIGNER_INFO info = { 0 };
6672 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6673
6674 SetLastError(0xdeadbeef);
6675 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6676 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6677 ok(!ret, "Expected failure, got %d\n", ret);
6678 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6679 {
6680 skip("no CMS_SIGNER_INFO encode support\n");
6681 return;
6682 }
6683 ok(GetLastError() == E_INVALIDARG,
6684 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6685 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6686 SetLastError(0xdeadbeef);
6687 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6688 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6689 ok(!ret, "Expected failure, got %d\n", ret);
6690 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6691 {
6692 skip("no CMS_SIGNER_INFO encode support\n");
6693 return;
6694 }
6695 ok(GetLastError() == E_INVALIDARG,
6696 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6697 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6698 * be a key id or a issuer serial number with at least the issuer set, and
6699 * the encoding must include PKCS_7_ASN_ENCODING.
6700 * (That isn't enough to be decoded, see decoding tests.)
6701 */
6702 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6703 sizeof(encodedCommonNameNoNull);
6704 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6705 SetLastError(0xdeadbeef);
6706 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6707 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6708 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6709 ok(!ret && GetLastError() == E_INVALIDARG,
6710 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6711 else
6712 {
6713 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6714 if (buf)
6715 {
6716 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6717 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6718 LocalFree(buf);
6719 }
6720 }
6721 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6722 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6723 SetLastError(0xdeadbeef);
6724 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6725 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6726 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6727 ok(!ret && GetLastError() == E_INVALIDARG,
6728 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6729 else
6730 {
6731 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6732 if (buf)
6733 {
6734 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6735 size);
6736 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6737 LocalFree(buf);
6738 }
6739 }
6740 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6741 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6742 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6743 SetLastError(0xdeadbeef);
6744 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6745 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6746 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6747 ok(!ret && GetLastError() == E_INVALIDARG,
6748 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6749 else
6750 {
6751 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6752 if (buf)
6753 {
6754 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6755 size);
6756 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6757 LocalFree(buf);
6758 }
6759 }
6760 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6761 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6762 * (see RFC 3852, section 5.3.)
6763 */
6764 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6765 U(info.SignerId).HashId.cbData = sizeof(hash);
6766 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6767 SetLastError(0xdeadbeef);
6768 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6769 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6770 ok(!ret && GetLastError() == E_INVALIDARG,
6771 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6772 /* Now with a hash algo */
6773 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6774 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6775 sizeof(encodedCommonNameNoNull);
6776 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6777 info.HashAlgorithm.pszObjId = oid1;
6778 SetLastError(0xdeadbeef);
6779 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6780 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6781 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6782 ok(!ret && GetLastError() == E_INVALIDARG,
6783 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6784 else
6785 {
6786 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6787 if (buf)
6788 {
6789 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6790 size);
6791 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6792 "Unexpected value\n");
6793 LocalFree(buf);
6794 }
6795 }
6796 info.HashEncryptionAlgorithm.pszObjId = oid2;
6797 SetLastError(0xdeadbeef);
6798 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6799 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6800 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6801 ok(!ret && GetLastError() == E_INVALIDARG,
6802 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6803 else
6804 {
6805 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6806 if (buf)
6807 {
6808 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6809 "Unexpected size %d\n", size);
6810 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6811 "Unexpected value\n");
6812 LocalFree(buf);
6813 }
6814 }
6815 info.EncryptedHash.cbData = sizeof(hash);
6816 info.EncryptedHash.pbData = (BYTE *)hash;
6817 SetLastError(0xdeadbeef);
6818 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6819 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6820 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6821 ok(!ret && GetLastError() == E_INVALIDARG,
6822 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6823 else
6824 {
6825 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6826 if (buf)
6827 {
6828 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6829 size);
6830 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6831 LocalFree(buf);
6832 }
6833 }
6834 }
6835
6836 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6837 {
6838 BOOL ret;
6839 LPBYTE buf = NULL;
6840 DWORD size = 0;
6841 CMSG_CMS_SIGNER_INFO *info;
6842 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6843
6844 /* A CMS signer can't be decoded without a serial number. */
6845 SetLastError(0xdeadbeef);
6846 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6847 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6848 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6849 ok(!ret, "expected failure\n");
6850 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6851 {
6852 skip("no CMS_SIGNER_INFO decode support\n");
6853 return;
6854 }
6855 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6856 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6857 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6858 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6859 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6860 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6861 if (buf)
6862 {
6863 info = (CMSG_CMS_SIGNER_INFO *)buf;
6864 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6865 info->dwVersion);
6866 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6867 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6868 info->SignerId.dwIdChoice);
6869 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6870 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6871 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6872 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6873 encodedCommonNameNoNull,
6874 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6875 "Unexpected value\n");
6876 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6877 sizeof(serialNum), "Unexpected size %d\n",
6878 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6879 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6880 serialNum, sizeof(serialNum)), "Unexpected value\n");
6881 LocalFree(buf);
6882 }
6883 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6884 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6885 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6886 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6887 if (buf)
6888 {
6889 info = (CMSG_CMS_SIGNER_INFO *)buf;
6890 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6891 info->dwVersion);
6892 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6893 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6894 info->SignerId.dwIdChoice);
6895 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6896 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6897 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6898 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6899 encodedCommonNameNoNull,
6900 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6901 "Unexpected value\n");
6902 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6903 sizeof(serialNum), "Unexpected size %d\n",
6904 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6905 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6906 serialNum, sizeof(serialNum)), "Unexpected value\n");
6907 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6908 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6909 LocalFree(buf);
6910 }
6911 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6912 PKCSSignerWithHashAndEncryptionAlgo,
6913 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6914 NULL, &buf, &size);
6915 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6916 if (buf)
6917 {
6918 info = (CMSG_CMS_SIGNER_INFO *)buf;
6919 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6920 info->dwVersion);
6921 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6922 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6923 info->SignerId.dwIdChoice);
6924 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6925 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6926 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6927 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6928 encodedCommonNameNoNull,
6929 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6930 "Unexpected value\n");
6931 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6932 sizeof(serialNum), "Unexpected size %d\n",
6933 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6934 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6935 serialNum, sizeof(serialNum)), "Unexpected value\n");
6936 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6937 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6938 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6939 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6940 LocalFree(buf);
6941 }
6942 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6943 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6944 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6945 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6946 if (buf)
6947 {
6948 info = (CMSG_CMS_SIGNER_INFO *)buf;
6949 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6950 info->dwVersion);
6951 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6952 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6953 info->SignerId.dwIdChoice);
6954 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6955 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6956 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6957 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6958 encodedCommonNameNoNull,
6959 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6960 "Unexpected value\n");
6961 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6962 sizeof(serialNum), "Unexpected size %d\n",
6963 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6964 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6965 serialNum, sizeof(serialNum)), "Unexpected value\n");
6966 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6967 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6968 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6969 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6970 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6971 info->EncryptedHash.cbData);
6972 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6973 "Unexpected value\n");
6974 LocalFree(buf);
6975 }
6976 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6977 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6978 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6979 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6980 if (buf)
6981 {
6982 info = (CMSG_CMS_SIGNER_INFO *)buf;
6983 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6984 info->dwVersion);
6985 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6986 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6987 info->SignerId.dwIdChoice);
6988 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6989 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6990 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6991 "Unexpected value\n");
6992 LocalFree(buf);
6993 }
6994 }
6995
6996 static BYTE emptyDNSPermittedConstraints[] = {
6997 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6998 static BYTE emptyDNSExcludedConstraints[] = {
6999 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7000 static BYTE DNSExcludedConstraints[] = {
7001 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7002 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7003 static BYTE permittedAndExcludedConstraints[] = {
7004 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7005 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7006 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7007 static BYTE permittedAndExcludedWithMinConstraints[] = {
7008 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7009 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7010 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7011 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7012 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7013 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7014 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7015
7016 static void test_encodeNameConstraints(DWORD dwEncoding)
7017 {
7018 BOOL ret;
7019 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7020 CERT_GENERAL_SUBTREE permitted = { { 0 } };
7021 CERT_GENERAL_SUBTREE excluded = { { 0 } };
7022 LPBYTE buf;
7023 DWORD size;
7024
7025 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7026 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7027 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7028 {
7029 skip("no X509_NAME_CONSTRAINTS encode support\n");
7030 return;
7031 }
7032 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7033 if (ret)
7034 {
7035 ok(size == sizeof(emptySequence), "Unexpected size\n");
7036 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7037 LocalFree(buf);
7038 }
7039 constraints.cPermittedSubtree = 1;
7040 constraints.rgPermittedSubtree = &permitted;
7041 SetLastError(0xdeadbeef);
7042 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7043 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7044 ok(!ret && GetLastError() == E_INVALIDARG,
7045 "Expected E_INVALIDARG, got %08x\n", GetLastError());
7046 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7047 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7048 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7049 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7050 if (ret)
7051 {
7052 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7053 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7054 "Unexpected value\n");
7055 LocalFree(buf);
7056 }
7057 constraints.cPermittedSubtree = 0;
7058 constraints.cExcludedSubtree = 1;
7059 constraints.rgExcludedSubtree = &excluded;
7060 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7061 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7062 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7063 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7064 if (ret)
7065 {
7066 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7067 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7068 "Unexpected value\n");
7069 LocalFree(buf);
7070 }
7071 U(excluded.Base).pwszURL = (LPWSTR)url;
7072 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7073 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7074 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7075 if (ret)
7076 {
7077 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7078 ok(!memcmp(buf, DNSExcludedConstraints, size),
7079 "Unexpected value\n");
7080 LocalFree(buf);
7081 }
7082 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7083 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7084 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7085 constraints.cPermittedSubtree = 1;
7086 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7087 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7088 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7089 if (ret)
7090 {
7091 ok(size == sizeof(permittedAndExcludedConstraints),
7092 "Unexpected size\n");
7093 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7094 "Unexpected value\n");
7095 LocalFree(buf);
7096 }
7097 permitted.dwMinimum = 5;
7098 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7099 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7100 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7101 if (ret)
7102 {
7103 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7104 "Unexpected size\n");
7105 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7106 "Unexpected value\n");
7107 LocalFree(buf);
7108 }
7109 permitted.fMaximum = TRUE;
7110 permitted.dwMaximum = 3;
7111 SetLastError(0xdeadbeef);
7112 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7113 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7114 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7115 if (ret)
7116 {
7117 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7118 "Unexpected size\n");
7119 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7120 "Unexpected value\n");
7121 LocalFree(buf);
7122 }
7123 }
7124
7125 struct EncodedNameConstraints
7126 {
7127 CRYPT_DATA_BLOB encoded;
7128 CERT_NAME_CONSTRAINTS_INFO constraints;
7129 };
7130
7131 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7132 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7133 static CERT_GENERAL_SUBTREE DNSSubtree = {
7134 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7135 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7136 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7137 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7138 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7139 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7140 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7141
7142 struct EncodedNameConstraints encodedNameConstraints[] = {
7143 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7144 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7145 { 1, &emptyDNSSubtree, 0, NULL } },
7146 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7147 { 0, NULL, 1, &emptyDNSSubtree } },
7148 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7149 { 0, NULL, 1, &DNSSubtree } },
7150 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7151 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7152 { { sizeof(permittedAndExcludedWithMinConstraints),
7153 permittedAndExcludedWithMinConstraints },
7154 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7155 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7156 permittedAndExcludedWithMinMaxConstraints },
7157 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7158 };
7159
7160 static void test_decodeNameConstraints(DWORD dwEncoding)
7161 {
7162 BOOL ret;
7163 DWORD i;
7164 CERT_NAME_CONSTRAINTS_INFO *constraints;
7165
7166 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7167 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7168 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7169 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7170 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7171 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7172 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7173 for (i = 0;
7174 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7175 i++)
7176 {
7177 DWORD size;
7178
7179 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7180 encodedNameConstraints[i].encoded.pbData,
7181 encodedNameConstraints[i].encoded.cbData,
7182 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7183 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7184 {
7185 skip("no X509_NAME_CONSTRAINTS decode support\n");
7186 return;
7187 }
7188 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7189 if (ret)
7190 {
7191 DWORD j;
7192
7193 if (constraints->cPermittedSubtree !=
7194 encodedNameConstraints[i].constraints.cPermittedSubtree)
7195 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7196 encodedNameConstraints[i].constraints.cPermittedSubtree,
7197 constraints->cPermittedSubtree);
7198 if (constraints->cPermittedSubtree ==
7199 encodedNameConstraints[i].constraints.cPermittedSubtree)
7200 {
7201 for (j = 0; j < constraints->cPermittedSubtree; j++)
7202 {
7203 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7204 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7205 }
7206 }
7207 if (constraints->cExcludedSubtree !=
7208 encodedNameConstraints[i].constraints.cExcludedSubtree)
7209 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7210 encodedNameConstraints[i].constraints.cExcludedSubtree,
7211 constraints->cExcludedSubtree);
7212 if (constraints->cExcludedSubtree ==
7213 encodedNameConstraints[i].constraints.cExcludedSubtree)
7214 {
7215 for (j = 0; j < constraints->cExcludedSubtree; j++)
7216 {
7217 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7218 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7219 }
7220 }
7221 LocalFree(constraints);
7222 }
7223 }
7224 }
7225
7226 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7227 'n','o','t','i','c','e',0 };
7228 static const BYTE noticeWithDisplayText[] = {
7229 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7230 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7231 0x00,0x69,0x00,0x63,0x00,0x65
7232 };
7233 static char org[] = "Wine";
7234 static int noticeNumbers[] = { 2,3 };
7235 static BYTE noticeWithReference[] = {
7236 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7237 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7238 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7239 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7240 };
7241
7242 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7243 {
7244 BOOL ret;
7245 LPBYTE buf;
7246 DWORD size;
7247 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7248 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7249
7250 memset(&notice, 0, sizeof(notice));
7251 ret = pCryptEncodeObjectEx(dwEncoding,
7252 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7253 NULL, &buf, &size);
7254 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7255 {
7256 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7257 return;
7258 }
7259 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7260 if (ret)
7261 {
7262 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7263 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7264 LocalFree(buf);
7265 }
7266 notice.pszDisplayText = noticeText;
7267 ret = pCryptEncodeObjectEx(dwEncoding,
7268 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7269 NULL, &buf, &size);
7270 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7271 if (ret)
7272 {
7273 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7274 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7275 LocalFree(buf);
7276 }
7277 reference.pszOrganization = org;
7278 reference.cNoticeNumbers = 2;
7279 reference.rgNoticeNumbers = noticeNumbers;
7280 notice.pNoticeReference = &reference;
7281 ret = pCryptEncodeObjectEx(dwEncoding,
7282 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7283 NULL, &buf, &size);
7284 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7285 if (ret)
7286 {
7287 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7288 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7289 LocalFree(buf);
7290 }
7291 }
7292
7293 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7294 {
7295 BOOL ret;
7296 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7297 DWORD size;
7298
7299 ret = pCryptDecodeObjectEx(dwEncoding,
7300 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7301 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7302 &notice, &size);
7303 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7304 {
7305 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7306 return;
7307 }
7308 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7309 if (ret)
7310 {
7311 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7312 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7313 LocalFree(notice);
7314 }
7315 ret = pCryptDecodeObjectEx(dwEncoding,
7316 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7317 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7318 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7320 if (ret)
7321 {
7322 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7323 "unexpected display text\n");
7324 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7325 LocalFree(notice);
7326 }
7327 ret = pCryptDecodeObjectEx(dwEncoding,
7328 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7329 noticeWithReference, sizeof(noticeWithReference),
7330 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7331 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7332 if (ret)
7333 {
7334 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7335 "unexpected display text\n");
7336 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7337 if (notice->pNoticeReference)
7338 {
7339 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7340 "unexpected organization %s\n",
7341 notice->pNoticeReference->pszOrganization);
7342 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7343 "expected 2 notice numbers, got %d\n",
7344 notice->pNoticeReference->cNoticeNumbers);
7345 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7346 "unexpected notice number %d\n",
7347 notice->pNoticeReference->rgNoticeNumbers[0]);
7348 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7349 "unexpected notice number %d\n",
7350 notice->pNoticeReference->rgNoticeNumbers[1]);
7351 }
7352 LocalFree(notice);
7353 }
7354 }
7355
7356 static char oid_any_policy[] = "2.5.29.32.0";
7357 static const BYTE policiesWithAnyPolicy[] = {
7358 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7359 };
7360 static char oid1[] = "1.2.3";
7361 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7362 static const BYTE twoPolicies[] = {
7363 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7364 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7365 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7366 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7367 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7368 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7369 };
7370
7371 static void test_encodeCertPolicies(DWORD dwEncoding)
7372 {
7373 BOOL ret;
7374 CERT_POLICIES_INFO info;
7375 CERT_POLICY_INFO policy[2];
7376 CERT_POLICY_QUALIFIER_INFO qualifier;
7377 LPBYTE buf;
7378 DWORD size;
7379
7380 memset(&info, 0, sizeof(info));
7381 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7382 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7383 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7384 if (ret)
7385 {
7386 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7387 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7388 LocalFree(buf);
7389 }
7390 memset(policy, 0, sizeof(policy));
7391 info.cPolicyInfo = 1;
7392 info.rgPolicyInfo = policy;
7393 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7394 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7395 ok(!ret && (GetLastError() == E_INVALIDARG ||
7396 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7397 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7398 policy[0].pszPolicyIdentifier = oid_any_policy;
7399 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7400 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7401 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7402 if (ret)
7403 {
7404 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7405 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7406 LocalFree(buf);
7407 }
7408 policy[1].pszPolicyIdentifier = oid1;
7409 memset(&qualifier, 0, sizeof(qualifier));
7410 qualifier.pszPolicyQualifierId = oid_user_notice;
7411 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7412 qualifier.Qualifier.pbData = noticeWithReference;
7413 policy[1].cPolicyQualifier = 1;
7414 policy[1].rgPolicyQualifier = &qualifier;
7415 info.cPolicyInfo = 2;
7416 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7417 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7418 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7419 if (ret)
7420 {
7421 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7422 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7423 LocalFree(buf);
7424 }
7425 }
7426
7427 static void test_decodeCertPolicies(DWORD dwEncoding)
7428 {
7429 BOOL ret;
7430 CERT_POLICIES_INFO *info;
7431 DWORD size;
7432
7433 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7434 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7435 &info, &size);
7436 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7437 if (ret)
7438 {
7439 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7440 info->cPolicyInfo);
7441 LocalFree(info);
7442 }
7443 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7444 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7445 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7446 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7447 if (ret)
7448 {
7449 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7450 info->cPolicyInfo);
7451 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7452 "unexpected policy id %s\n",
7453 info->rgPolicyInfo[0].pszPolicyIdentifier);
7454 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7455 "unexpected policy qualifier count %d\n",
7456 info->rgPolicyInfo[0].cPolicyQualifier);
7457 LocalFree(info);
7458 }
7459 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7460 twoPolicies, sizeof(twoPolicies),
7461 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7462 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7463 if (ret)
7464 {
7465 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7466 info->cPolicyInfo);
7467 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7468 "unexpected policy id %s\n",
7469 info->rgPolicyInfo[0].pszPolicyIdentifier);
7470 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7471 "unexpected policy qualifier count %d\n",
7472 info->rgPolicyInfo[0].cPolicyQualifier);
7473 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7474 "unexpected policy id %s\n",
7475 info->rgPolicyInfo[1].pszPolicyIdentifier);
7476 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7477 "unexpected policy qualifier count %d\n",
7478 info->rgPolicyInfo[1].cPolicyQualifier);
7479 ok(!strcmp(
7480 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7481 oid_user_notice), "unexpected policy qualifier id %s\n",
7482 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7483 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7484 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7485 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7486 ok(!memcmp(
7487 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7488 noticeWithReference, sizeof(noticeWithReference)),
7489 "unexpected qualifier value\n");
7490 LocalFree(info);
7491 }
7492 }
7493
7494 static const BYTE policyMappingWithOneMapping[] = {
7495 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7496 static const BYTE policyMappingWithTwoMappings[] = {
7497 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7498 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7499 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7500 szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7501
7502 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7503 {
7504 static char oid2[] = "2.3.4";
7505 static char oid3[] = "1.3.4";
7506 static char oid4[] = "2.5.6";
7507 BOOL ret;
7508 CERT_POLICY_MAPPINGS_INFO info = { 0 };
7509 CERT_POLICY_MAPPING mapping[2];
7510 LPBYTE buf;
7511 DWORD size, i;
7512
7513 /* Each of the mapping OIDs is equivalent, so check with all of them */
7514 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7515 {
7516 memset(&info, 0, sizeof(info));
7517 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7518 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7519 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7520 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7521 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7522 {
7523 win_skip("no policy mappings support\n");
7524 return;
7525 }
7526 if (ret)
7527 {
7528 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7529 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7530 "unexpected value\n");
7531 LocalFree(buf);
7532 }
7533 mapping[0].pszIssuerDomainPolicy = NULL;
7534 mapping[0].pszSubjectDomainPolicy = NULL;
7535 info.cPolicyMapping = 1;
7536 info.rgPolicyMapping = mapping;
7537 SetLastError(0xdeadbeef);
7538 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7539 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7540 ok(!ret && GetLastError() == E_INVALIDARG,
7541 "expected E_INVALIDARG, got %08x\n", GetLastError());
7542 mapping[0].pszIssuerDomainPolicy = oid1;
7543 mapping[0].pszSubjectDomainPolicy = oid2;
7544 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7545 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7546 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7547 if (ret)
7548 {
7549 ok(size == sizeof(policyMappingWithOneMapping),
7550 "unexpected size %d\n", size);
7551 ok(!memcmp(buf, policyMappingWithOneMapping, size),
7552 "unexpected value\n");
7553 LocalFree(buf);
7554 }
7555 mapping[1].pszIssuerDomainPolicy = oid3;
7556 mapping[1].pszSubjectDomainPolicy = oid4;
7557 info.cPolicyMapping = 2;
7558 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7559 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7560 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7561 if (ret)
7562 {
7563 ok(size == sizeof(policyMappingWithTwoMappings),
7564 "unexpected size %d\n", size);
7565 ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7566 "unexpected value\n");
7567 LocalFree(buf);
7568 }
7569 }
7570 }
7571
7572 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7573 {
7574 DWORD size, i;
7575 CERT_POLICY_MAPPINGS_INFO *info;
7576 BOOL ret;
7577
7578 /* Each of the mapping OIDs is equivalent, so check with all of them */
7579 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7580 {
7581 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7582 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7583 &info, &size);
7584 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7585 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7586 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7587 {
7588 win_skip("no policy mappings support\n");
7589 return;
7590 }
7591 if (ret)
7592 {
7593 ok(info->cPolicyMapping == 0,
7594 "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7595 LocalFree(info);
7596 }
7597 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7598 policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7599 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7600 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7601 if (ret)
7602 {
7603 ok(info->cPolicyMapping == 1,
7604 "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7605 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7606 "unexpected issuer policy %s\n",
7607 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7608 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7609 "2.3.4"), "unexpected subject policy %s\n",
7610 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7611 LocalFree(info);
7612 }
7613 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7614 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7615 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7616 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7617 if (ret)
7618 {
7619 ok(info->cPolicyMapping == 2,
7620 "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7621 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7622 "unexpected issuer policy %s\n",
7623 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7624 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7625 "2.3.4"), "unexpected subject policy %s\n",
7626 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7627 ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7628 "unexpected issuer policy %s\n",
7629 info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7630 ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7631 "2.5.6"), "unexpected subject policy %s\n",
7632 info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7633 LocalFree(info);
7634 }
7635 }
7636 }
7637
7638 static const BYTE policyConstraintsWithRequireExplicit[] = {
7639 0x30,0x03,0x80,0x01,0x00 };
7640 static const BYTE policyConstraintsWithInhibitMapping[] = {
7641 0x30,0x03,0x81,0x01,0x01 };
7642 static const BYTE policyConstraintsWithBoth[] = {
7643 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7644
7645 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7646 {
7647 CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7648 LPBYTE buf;
7649 DWORD size;
7650 BOOL ret;
7651
7652 /* Even though RFC 5280 explicitly states CAs must not issue empty
7653 * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7654 */
7655 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7656 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7657 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7658 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7659 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7660 {
7661 win_skip("no policy constraints support\n");
7662 return;
7663 }
7664 if (ret)
7665 {
7666 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7667 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7668 "unexpected value\n");
7669 LocalFree(buf);
7670 }
7671 /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7672 * is not, then a skip of 0 is encoded.
7673 */
7674 info.fRequireExplicitPolicy = TRUE;
7675 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7676 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7677 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7678 if (ret)
7679 {
7680 ok(size == sizeof(policyConstraintsWithRequireExplicit),
7681 "unexpected size %d\n", size);
7682 ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7683 sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7684 LocalFree(buf);
7685 }
7686 /* With inhibit policy mapping */
7687 info.fRequireExplicitPolicy = FALSE;
7688 info.dwRequireExplicitPolicySkipCerts = 0;
7689 info.fInhibitPolicyMapping = TRUE;
7690 info.dwInhibitPolicyMappingSkipCerts = 1;
7691 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7692 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7693 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7694 if (ret)
7695 {
7696 ok(size == sizeof(policyConstraintsWithInhibitMapping),
7697 "unexpected size %d\n", size);
7698 ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7699 sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7700 LocalFree(buf);
7701 }
7702 /* And with both */
7703 info.fRequireExplicitPolicy = TRUE;
7704 info.dwRequireExplicitPolicySkipCerts = 1;
7705 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7706 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7707 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7708 if (ret)
7709 {
7710 ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7711 size);
7712 ok(!memcmp(buf, policyConstraintsWithBoth,
7713 sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7714 LocalFree(buf);
7715 }
7716 }
7717
7718 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7719 {
7720 CERT_POLICY_CONSTRAINTS_INFO *info;
7721 DWORD size;
7722 BOOL ret;
7723
7724 /* Again, even though CAs must not issue such constraints, they can be
7725 * decoded.
7726 */
7727 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7728 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7729 &info, &size);
7730 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7731 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7732 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7733 {
7734 win_skip("no policy mappings support\n");
7735 return;
7736 }
7737 if (ret)
7738 {
7739 ok(!info->fRequireExplicitPolicy,
7740 "expected require explicit = FALSE\n");
7741 ok(!info->fInhibitPolicyMapping,
7742 "expected implicit mapping = FALSE\n");
7743 LocalFree(info);
7744 }
7745 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7746 policyConstraintsWithRequireExplicit,
7747 sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7748 NULL, &info, &size);
7749 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7750 if (ret)
7751 {
7752 ok(info->fRequireExplicitPolicy,
7753 "expected require explicit = TRUE\n");
7754 ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7755 info->dwRequireExplicitPolicySkipCerts);
7756 ok(!info->fInhibitPolicyMapping,
7757 "expected implicit mapping = FALSE\n");
7758 LocalFree(info);
7759 }
7760 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7761 policyConstraintsWithInhibitMapping,
7762 sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7763 NULL, &info, &size);
7764 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7765 if (ret)
7766 {
7767 ok(!info->fRequireExplicitPolicy,
7768 "expected require explicit = FALSE\n");
7769 ok(info->fInhibitPolicyMapping,
7770 "expected implicit mapping = TRUE\n");
7771 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7772 info->dwInhibitPolicyMappingSkipCerts);
7773 LocalFree(info);
7774 }
7775 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7776 policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7777 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7778 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7779 if (ret)
7780 {
7781 ok(info->fRequireExplicitPolicy,
7782 "expected require explicit = TRUE\n");
7783 ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7784 info->dwRequireExplicitPolicySkipCerts);
7785 ok(info->fInhibitPolicyMapping,
7786 "expected implicit mapping = TRUE\n");
7787 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7788 info->dwInhibitPolicyMappingSkipCerts);
7789 LocalFree(info);
7790 }
7791 }
7792
7793 /* Free *pInfo with HeapFree */
7794 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7795 {
7796 BOOL ret;
7797 DWORD size = 0;
7798 HCRYPTKEY key;
7799
7800 /* This crashes
7801 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7802 */
7803 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7804 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7805 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7806 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7807 &size);
7808 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7809 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7810 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7811 NULL, &size);
7812 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7813 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7814 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7815 0, NULL, NULL, &size);
7816 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7817 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7818 /* Test with no key */
7819 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7820 0, NULL, NULL, &size);
7821 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7822 GetLastError());
7823 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7824 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7825 if (ret)
7826 {
7827 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7828 NULL, 0, NULL, NULL, &size);
7829 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7830 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7831 if (*pInfo)
7832 {
7833 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7834 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7835 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7836 GetLastError());
7837 if (ret)
7838 {
7839 /* By default (we passed NULL as the OID) the OID is
7840 * szOID_RSA_RSA.
7841 */
7842 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7843 "Expected %s, got %s\n", szOID_RSA_RSA,
7844 (*pInfo)->Algorithm.pszObjId);
7845 }
7846 }
7847 }
7848 CryptDestroyKey(key);
7849 }
7850
7851 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7852 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7853 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7854 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7855 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7856 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7857 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7858 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7859 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7860 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7861 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7862 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7863 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7864 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7865 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7866 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7867 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7868 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7869 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7870 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7871 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7872 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7873 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7874 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7875 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7876
7877 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7878 {
7879 BOOL ret;
7880 HCRYPTKEY key;
7881 PCCERT_CONTEXT context;
7882 DWORD dwSize;
7883 ALG_ID ai;
7884
7885 /* These crash
7886 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7887 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7888 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7889 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7890 NULL);
7891 */
7892 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7893 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7894 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7895 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7896 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7897 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7898 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7899 &key);
7900 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7901 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7902
7903 /* Export key with standard algorithm (CALG_RSA_KEYX) */
7904 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7905 &key);
7906 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7907
7908 dwSize = sizeof(ai);
7909 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7910 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7911 if(ret)
7912 {
7913 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7914 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7915 }
7916
7917 CryptDestroyKey(key);
7918
7919 /* Repeat with forced algorithm */
7920 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7921 &key);
7922 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7923
7924 dwSize = sizeof(ai);
7925 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7926 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7927 if(ret)
7928 {
7929 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7930 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7931 }
7932
7933 CryptDestroyKey(key);
7934
7935 /* Test importing a public key from a certificate context */
7936 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7937 sizeof(expiredCert));
7938 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7939 GetLastError());
7940 if (context)
7941 {
7942 ok(!strcmp(szOID_RSA_RSA,
7943 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7944 "Expected %s, got %s\n", szOID_RSA_RSA,
7945 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7946 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7947 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7948 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7949 CryptDestroyKey(key);
7950 CertFreeCertificateContext(context);
7951 }
7952 }
7953
7954 static const char cspName[] = "WineCryptTemp";
7955
7956 static void testPortPublicKeyInfo(void)
7957 {
7958 HCRYPTPROV csp;
7959 BOOL ret;
7960 PCERT_PUBLIC_KEY_INFO info = NULL;
7961
7962 /* Just in case a previous run failed, delete this thing */
7963 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7964 CRYPT_DELETEKEYSET);
7965 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7966 CRYPT_NEWKEYSET);
7967
7968 testExportPublicKey(csp, &info);
7969 testImportPublicKey(csp, info);
7970
7971 HeapFree(GetProcessHeap(), 0, info);
7972 CryptReleaseContext(csp, 0);
7973 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7974 CRYPT_DELETEKEYSET);
7975 }
7976
7977 START_TEST(encode)
7978 {
7979 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7980 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7981 HMODULE hCrypt32;
7982 DWORD i;
7983
7984 hCrypt32 = GetModuleHandleA("crypt32.dll");
7985 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7986 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7987 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7988 {
7989 win_skip("CryptDecodeObjectEx() is not available\n");
7990 return;
7991 }
7992
7993 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7994 {
7995 test_encodeInt(encodings[i]);
7996 test_decodeInt(encodings[i]);
7997 test_encodeEnumerated(encodings[i]);
7998 test_decodeEnumerated(encodings[i]);
7999 test_encodeFiletime(encodings[i]);
8000 test_decodeFiletime(encodings[i]);
8001 test_encodeName(encodings[i]);
8002 test_decodeName(encodings[i]);
8003 test_encodeUnicodeName(encodings[i]);
8004 test_decodeUnicodeName(encodings[i]);
8005 test_encodeNameValue(encodings[i]);
8006 test_decodeNameValue(encodings[i]);
8007 test_encodeUnicodeNameValue(encodings[i]);
8008 test_decodeUnicodeNameValue(encodings[i]);
8009 test_encodeAltName(encodings[i]);
8010 test_decodeAltName(encodings[i]);
8011 test_encodeOctets(encodings[i]);
8012 test_decodeOctets(encodings[i]);
8013 test_encodeBits(encodings[i]);
8014 test_decodeBits(encodings[i]);
8015 test_encodeBasicConstraints(encodings[i]);
8016 test_decodeBasicConstraints(encodings[i]);
8017 test_encodeRsaPublicKey(encodings[i]);
8018 test_decodeRsaPublicKey(encodings[i]);
8019 test_encodeSequenceOfAny(encodings[i]);
8020 test_decodeSequenceOfAny(encodings[i]);
8021 test_encodeExtensions(encodings[i]);
8022 test_decodeExtensions(encodings[i]);
8023 test_encodePublicKeyInfo(encodings[i]);
8024 test_decodePublicKeyInfo(encodings[i]);
8025 test_encodeCertToBeSigned(encodings[i]);
8026 test_decodeCertToBeSigned(encodings[i]);
8027 test_encodeCert(encodings[i]);
8028 test_decodeCert(encodings[i]);
8029 test_encodeCRLDistPoints(encodings[i]);
8030 test_decodeCRLDistPoints(encodings[i]);
8031 test_encodeCRLIssuingDistPoint(encodings[i]);
8032 test_decodeCRLIssuingDistPoint(encodings[i]);
8033 test_encodeCRLToBeSigned(encodings[i]);
8034 test_decodeCRLToBeSigned(encodings[i]);
8035 test_encodeEnhancedKeyUsage(encodings[i]);
8036 test_decodeEnhancedKeyUsage(encodings[i]);
8037 test_encodeAuthorityKeyId(encodings[i]);
8038 test_decodeAuthorityKeyId(encodings[i]);
8039 test_encodeAuthorityKeyId2(encodings[i]);
8040 test_decodeAuthorityKeyId2(encodings[i]);
8041 test_encodeAuthorityInfoAccess(encodings[i]);
8042 test_decodeAuthorityInfoAccess(encodings[i]);
8043 test_encodeCTL(encodings[i]);
8044 test_decodeCTL(encodings[i]);
8045 test_encodePKCSContentInfo(encodings[i]);
8046 test_decodePKCSContentInfo(encodings[i]);
8047 test_encodePKCSAttribute(encodings[i]);
8048 test_decodePKCSAttribute(encodings[i]);
8049 test_encodePKCSAttributes(encodings[i]);
8050 test_decodePKCSAttributes(encodings[i]);
8051 test_encodePKCSSMimeCapabilities(encodings[i]);
8052 test_decodePKCSSMimeCapabilities(encodings[i]);
8053 test_encodePKCSSignerInfo(encodings[i]);
8054 test_decodePKCSSignerInfo(encodings[i]);
8055 test_encodeCMSSignerInfo(encodings[i]);
8056 test_decodeCMSSignerInfo(encodings[i]);
8057 test_encodeNameConstraints(encodings[i]);
8058 test_decodeNameConstraints(encodings[i]);
8059 test_encodePolicyQualifierUserNotice(encodings[i]);
8060 test_decodePolicyQualifierUserNotice(encodings[i]);
8061 test_encodeCertPolicies(encodings[i]);
8062 test_decodeCertPolicies(encodings[i]);
8063 test_encodeCertPolicyMappings(encodings[i]);
8064 test_decodeCertPolicyMappings(encodings[i]);
8065 test_encodeCertPolicyConstraints(encodings[i]);
8066 test_decodeCertPolicyConstraints(encodings[i]);
8067 }
8068 testPortPublicKeyInfo();
8069 }