2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "wine/test.h"
35 static const BYTE bin1[] = {0x02,0x01,0x01,0};
36 static const BYTE bin2[] = {0x02,0x01,0x7f,0};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80,0};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00,0};
39 static const BYTE bin5[] = {0x02,0x01,0x80,0};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f,0};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d,0};
43 static const struct encodedInt ints[] = {
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
68 static const struct encodedBigInt bigInts[] = {
69 { bin8, bin9, bin10 },
70 { bin11, bin12, bin13 },
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80 { bin14, bin15, NULL },
81 { bin16, bin17, NULL },
84 static void test_encodeInt(DWORD dwEncoding)
89 CRYPT_INTEGER_BLOB blob;
92 /* CryptEncodeObjectEx with NULL bufSize crashes..
93 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
96 /* check bogus encoding */
97 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
99 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
101 /* check with NULL integer buffer. Windows XP incorrectly returns an
104 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
106 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
108 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
110 /* encode as normal integer */
111 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112 NULL, NULL, &bufSize);
113 ok(ret, "Expected success, got %ld\n", GetLastError());
114 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
116 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
119 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
121 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122 buf[1], ints[i].encoded[1]);
123 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
127 /* encode as multibyte integer */
128 blob.cbData = sizeof(ints[i].val);
129 blob.pbData = (BYTE *)&ints[i].val;
130 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131 0, NULL, NULL, &bufSize);
132 ok(ret, "Expected success, got %ld\n", GetLastError());
133 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
135 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
138 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
140 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141 buf[1], ints[i].encoded[1]);
142 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
147 /* encode a couple bigger ints, just to show it's little-endian and leading
148 * sign bytes are dropped
150 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
152 blob.cbData = strlen((const char*)bigInts[i].val);
153 blob.pbData = (BYTE *)bigInts[i].val;
154 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155 0, NULL, NULL, &bufSize);
156 ok(ret, "Expected success, got %ld\n", GetLastError());
157 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
159 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
162 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
164 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165 buf[1], bigInts[i].encoded[1]);
166 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167 bigInts[i].encoded[1] + 1),
168 "Encoded value didn't match expected\n");
172 /* and, encode some uints */
173 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
175 blob.cbData = strlen((const char*)bigUInts[i].val);
176 blob.pbData = (BYTE*)bigUInts[i].val;
177 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178 0, NULL, NULL, &bufSize);
179 ok(ret, "Expected success, got %ld\n", GetLastError());
180 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
182 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
185 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
187 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188 buf[1], bigUInts[i].encoded[1]);
189 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190 bigUInts[i].encoded[1] + 1),
191 "Encoded value didn't match expected\n");
197 static void test_decodeInt(DWORD dwEncoding)
199 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
208 /* CryptDecodeObjectEx with NULL bufSize crashes..
209 ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
210 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212 /* check bogus encoding */
213 ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
214 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
215 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
216 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
217 /* check with NULL integer buffer */
218 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
221 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
222 /* check with a valid, but too large, integer */
223 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
224 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
225 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
226 "Expected CRYPT_E_ASN1_LARGE, got %ld\n", GetLastError());
227 /* check with a DER-encoded string */
228 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
231 "Expected CRYPT_E_ASN1_BADTAG, got %ld\n", GetLastError());
232 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
234 /* When the output buffer is NULL, this always succeeds */
235 SetLastError(0xdeadbeef);
236 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239 ok(ret && GetLastError() == NOERROR,
240 "Expected success and NOERROR, got %ld\n", GetLastError());
241 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
243 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
245 ok(bufSize == sizeof(int), "Expected size %d, got %ld\n", sizeof(int),
247 ok(buf != NULL, "Expected allocated buffer\n");
250 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251 ints[i].val, *(int *)buf);
255 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
257 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
258 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
260 ok(ret && GetLastError() == NOERROR,
261 "Expected success and NOERROR, got %ld\n", GetLastError());
262 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
263 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
264 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
265 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
266 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
267 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
269 ok(buf != NULL, "Expected allocated buffer\n");
272 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
274 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
275 "Expected len %d, got %ld\n", strlen((const char*)bigInts[i].decoded),
277 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
278 "Unexpected value\n");
282 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
284 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
285 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
287 ok(ret && GetLastError() == NOERROR,
288 "Expected success and NOERROR, got %ld\n", GetLastError());
289 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
290 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
291 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
292 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
293 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
294 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
296 ok(buf != NULL, "Expected allocated buffer\n");
299 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
301 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302 "Expected len %d, got %ld\n", strlen((const char*)bigUInts[i].val),
304 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305 "Unexpected value\n");
309 /* Decode the value 1 with long-form length */
310 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
312 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
315 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
318 /* Try to decode some bogus large items */
319 /* The buffer size is smaller than the encoded length, so this should fail
320 * with CRYPT_E_ASN1_EOD if it's being decoded.
321 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
322 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
323 * So this test unfortunately isn't useful.
324 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
325 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
326 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
327 "Expected CRYPT_E_ASN1_LARGE, got %08lx\n", GetLastError());
329 /* This will try to decode the buffer and overflow it, check that it's
332 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
333 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
334 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
335 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
338 static const BYTE bin18[] = {0x0a,0x01,0x01,0};
339 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80,0};
341 /* These are always encoded unsigned, and aren't constrained to be any
344 static const struct encodedInt enums[] = {
349 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
352 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
353 szOID_CRL_REASON_CODE };
355 static void test_encodeEnumerated(DWORD dwEncoding)
359 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
361 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
367 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
368 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
370 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
374 "Got unexpected type %d for enumerated (expected 0xa)\n",
376 ok(buf[1] == enums[j].encoded[1],
377 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
378 ok(!memcmp(buf + 1, enums[j].encoded + 1,
379 enums[j].encoded[1] + 1),
380 "Encoded value of 0x%08x didn't match expected\n",
388 static void test_decodeEnumerated(DWORD dwEncoding)
392 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
394 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
397 DWORD bufSize = sizeof(int);
400 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
401 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
402 (BYTE *)&val, &bufSize);
403 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
404 ok(bufSize == sizeof(int),
405 "Got unexpected size %ld for enumerated (expected %d)\n",
406 bufSize, sizeof(int));
407 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
413 struct encodedFiletime
416 const BYTE *encodedTime;
419 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
420 const struct encodedFiletime *time)
427 ret = SystemTimeToFileTime(&time->sysTime, &ft);
428 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
429 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
430 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
431 /* years other than 1950-2050 are not allowed for encodings other than
432 * X509_CHOICE_OF_TIME.
434 if (structType == X509_CHOICE_OF_TIME ||
435 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
437 ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
439 ok(buf != NULL, "Expected an allocated buffer\n");
442 ok(buf[0] == time->encodedTime[0],
443 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
445 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %ld\n",
446 time->encodedTime[1], bufSize);
447 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
448 "Got unexpected value for time encoding\n");
453 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
454 "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
457 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
458 const struct encodedFiletime *time)
460 FILETIME ft1 = { 0 }, ft2 = { 0 };
461 DWORD size = sizeof(ft2);
464 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
465 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
466 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
467 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
468 /* years other than 1950-2050 are not allowed for encodings other than
469 * X509_CHOICE_OF_TIME.
471 if (structType == X509_CHOICE_OF_TIME ||
472 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
474 ok(ret, "CryptDecodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
476 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
477 "Got unexpected value for time decoding\n");
480 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
481 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
484 static const BYTE bin20[] = {
485 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z',0};
486 static const BYTE bin21[] = {
487 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z',0};
488 static const BYTE bin22[] = {
489 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z',0};
491 static const struct encodedFiletime times[] = {
492 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
493 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
494 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
497 static void test_encodeFiletime(DWORD dwEncoding)
501 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
503 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
504 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
505 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
509 static const BYTE bin23[] = {
510 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z',0};
511 static const BYTE bin24[] = {
512 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z',0};
513 static const BYTE bin25[] = {
514 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0',0};
515 static const BYTE bin26[] = {
516 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0',0};
517 static const BYTE bin27[] = {
518 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5',0};
519 static const BYTE bin28[] = {
520 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6',0};
521 static const BYTE bin29[] = {
522 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0',0};
523 static const BYTE bin30[] = {
524 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z',0};
525 static const BYTE bin31[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1',0};
527 static const BYTE bin32[] = {
528 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1',0};
529 static const BYTE bin33[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0',0};
531 static const BYTE bin34[] = {
532 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0',0};
533 static const BYTE bin35[] = {
534 0x17,0x08, '4','5','0','6','0','6','1','6',0};
535 static const BYTE bin36[] = {
536 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z',0};
537 static const BYTE bin37[] = {
538 0x18,0x04, '2','1','4','5',0};
539 static const BYTE bin38[] = {
540 0x18,0x08, '2','1','4','5','0','6','0','6',0};
542 static void test_decodeFiletime(DWORD dwEncoding)
544 static const struct encodedFiletime otherTimes[] = {
545 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
546 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
547 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
548 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
549 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
550 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
551 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
552 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
553 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
554 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
555 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
556 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
558 /* An oddball case that succeeds in Windows, but doesn't seem correct
559 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
561 static const unsigned char *bogusTimes[] = {
562 /* oddly, this succeeds on Windows, with year 2765
563 "\x18" "\x0f" "21r50606161000Z",
571 FILETIME ft1 = { 0 }, ft2 = { 0 };
574 /* Check bogus length with non-NULL buffer */
575 ret = SystemTimeToFileTime(×[0].sysTime, &ft1);
576 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
578 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
579 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
580 ok(!ret && GetLastError() == ERROR_MORE_DATA,
581 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
583 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
585 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
586 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
587 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
589 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
591 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
592 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
593 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
595 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
598 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
599 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
600 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
601 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
611 static const char commonName[] = "Juan Lang";
612 static const char surName[] = "Lang";
613 static const char bogusIA5[] = "\x80";
614 static const char bogusPrintable[] = "~";
615 static const char bogusNumeric[] = "A";
616 static const struct EncodedName names[] = {
617 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
618 { sizeof(commonName), (BYTE *)commonName } },
619 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0aJuan Lang" },
620 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
621 { sizeof(commonName), (BYTE *)commonName } },
622 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x16\x0aJuan Lang" },
623 { { szOID_SUR_NAME, CERT_RDN_IA5_STRING,
624 { sizeof(surName), (BYTE *)surName } },
625 "\x30\x10\x31\x0e\x30\x0c\x06\x03\x55\x04\x04\x16\x05Lang" },
626 { { NULL, CERT_RDN_PRINTABLE_STRING,
627 { sizeof(commonName), (BYTE *)commonName } },
628 "\x30\x12\x31\x10\x30\x0e\x06\x00\x13\x0aJuan Lang" },
629 /* The following test isn't a very good one, because it doesn't encode any
630 * Japanese characters. I'm leaving it out for now.
631 { { szOID_COMMON_NAME, CERT_RDN_T61_STRING,
632 { sizeof(commonName), (BYTE *)commonName } },
633 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x14\x0aJuan Lang" },
635 /* The following tests succeed under Windows, but really should fail,
636 * they contain characters that are illegal for the encoding. I'm
637 * including them to justify my lazy encoding.
639 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
640 { sizeof(bogusIA5), (BYTE *)bogusIA5 } },
641 "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x16\x02\x80" },
642 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
643 { sizeof(bogusPrintable), (BYTE *)bogusPrintable } },
644 "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x13\x02\x7e" },
645 { { szOID_COMMON_NAME, CERT_RDN_NUMERIC_STRING,
646 { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
647 "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x12\x02\x41" },
650 static const BYTE emptyName[] = { 0x30, 0 };
651 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
652 static const BYTE twoRDNs[] = "\x30\x23\x31\x21\x30\x0c\x06\x03\x55\x04\x04"
653 "\x13\x05\x4c\x61\x6e\x67\x00\x30\x11\x06\x03\x55\x04\x03"
654 "\x13\x0a\x4a\x75\x61\x6e\x20\x4c\x61\x6e\x67";
656 static void test_encodeName(DWORD dwEncoding)
658 CERT_RDN_ATTR attrs[2];
665 /* Test with NULL pvStructInfo */
666 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
667 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
668 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
669 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
670 /* Test with empty CERT_NAME_INFO */
673 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
674 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
675 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
678 ok(!memcmp(buf, emptyName, sizeof(emptyName)),
679 "Got unexpected encoding for empty name\n");
682 /* Test with bogus CERT_RDN */
684 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
685 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
686 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
687 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
688 /* Test with empty CERT_RDN */
690 rdn.rgRDNAttr = NULL;
693 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
694 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
695 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
698 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
699 "Got unexpected encoding for empty RDN array\n");
702 /* Test with bogus attr array */
704 rdn.rgRDNAttr = NULL;
705 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
706 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
707 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
708 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
709 /* oddly, a bogus OID is accepted by Windows XP; not testing.
710 attrs[0].pszObjId = "bogus";
711 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
712 attrs[0].Value.cbData = sizeof(commonName);
713 attrs[0].Value.pbData = (BYTE *)commonName;
715 rdn.rgRDNAttr = attrs;
716 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
717 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
718 ok(!ret, "Expected failure, got success\n");
720 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
721 * the encoded attributes to be swapped.
723 attrs[0].pszObjId = szOID_COMMON_NAME;
724 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
725 attrs[0].Value.cbData = sizeof(commonName);
726 attrs[0].Value.pbData = (BYTE *)commonName;
727 attrs[1].pszObjId = szOID_SUR_NAME;
728 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
729 attrs[1].Value.cbData = sizeof(surName);
730 attrs[1].Value.pbData = (BYTE *)surName;
732 rdn.rgRDNAttr = attrs;
733 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
734 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
735 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
738 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
739 "Got unexpected encoding for two RDN array\n");
742 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
744 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
745 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
746 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
747 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
748 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
749 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
752 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
753 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
754 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
755 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
758 ok(size == names[i].encoded[1] + 2, "Expected size %d, got %ld\n",
759 names[i].encoded[1] + 2, size);
760 ok(!memcmp(buf, names[i].encoded, names[i].encoded[1] + 2),
761 "Got unexpected encoding\n");
767 static void compareNames(const CERT_NAME_INFO *expected,
768 const CERT_NAME_INFO *got)
770 ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
771 expected->cRDN, got->cRDN);
774 ok(got->rgRDN[0].cRDNAttr == expected->rgRDN[0].cRDNAttr,
775 "Expected %ld RDN attrs, got %ld\n", expected->rgRDN[0].cRDNAttr,
776 got->rgRDN[0].cRDNAttr);
777 if (expected->rgRDN[0].cRDNAttr)
779 if (expected->rgRDN[0].rgRDNAttr[0].pszObjId &&
780 strlen(expected->rgRDN[0].rgRDNAttr[0].pszObjId))
782 ok(got->rgRDN[0].rgRDNAttr[0].pszObjId != NULL,
783 "Expected OID %s, got NULL\n",
784 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
785 if (got->rgRDN[0].rgRDNAttr[0].pszObjId)
786 ok(!strcmp(got->rgRDN[0].rgRDNAttr[0].pszObjId,
787 expected->rgRDN[0].rgRDNAttr[0].pszObjId),
788 "Got unexpected OID %s, expected %s\n",
789 got->rgRDN[0].rgRDNAttr[0].pszObjId,
790 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
792 ok(got->rgRDN[0].rgRDNAttr[0].Value.cbData ==
793 expected->rgRDN[0].rgRDNAttr[0].Value.cbData,
794 "Unexpected data size, got %ld, expected %ld\n",
795 got->rgRDN[0].rgRDNAttr[0].Value.cbData,
796 expected->rgRDN[0].rgRDNAttr[0].Value.cbData);
797 if (expected->rgRDN[0].rgRDNAttr[0].Value.pbData)
798 ok(!memcmp(got->rgRDN[0].rgRDNAttr[0].Value.pbData,
799 expected->rgRDN[0].rgRDNAttr[0].Value.pbData,
800 expected->rgRDN[0].rgRDNAttr[0].Value.cbData),
801 "Unexpected value\n");
806 static void test_decodeName(DWORD dwEncoding)
813 CERT_NAME_INFO info = { 1, &rdn };
815 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
817 /* When the output buffer is NULL, this always succeeds */
818 SetLastError(0xdeadbeef);
819 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
820 names[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
821 ok(ret && GetLastError() == NOERROR,
822 "Expected success and NOERROR, got %08lx\n", GetLastError());
823 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
824 names[i].encoded[1] + 2,
825 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
826 (BYTE *)&buf, &bufSize);
827 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
829 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
832 compareNames((CERT_NAME_INFO *)buf, &info);
836 /* test empty name */
838 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyName,
840 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
841 (BYTE *)&buf, &bufSize);
842 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
843 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
844 * decoder works the same way, so only test the count.
848 ok(bufSize == sizeof(CERT_NAME_INFO),
849 "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
850 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
851 "Expected 0 RDNs in empty info, got %ld\n",
852 ((CERT_NAME_INFO *)buf)->cRDN);
857 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
859 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
860 (BYTE *)&buf, &bufSize);
861 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
864 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
866 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
867 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
868 "Got unexpected value for empty RDN\n");
871 /* test two RDN attrs */
873 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
875 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
876 (BYTE *)&buf, &bufSize);
877 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
880 CERT_RDN_ATTR attrs[] = {
881 { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
883 { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
884 (BYTE *)commonName } },
887 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
888 rdn.rgRDNAttr = attrs;
889 compareNames((CERT_NAME_INFO *)buf, &info);
894 static const BYTE emptyAltName[] = { 0x30, 0x00 };
895 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
896 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
897 'h','q','.','o','r','g',0 };
898 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
899 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
901 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
903 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
904 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
905 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
906 static const BYTE localhost[] = { 127, 0, 0, 1 };
907 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
910 static void test_encodeAltName(DWORD dwEncoding)
912 CERT_ALT_NAME_INFO info = { 0 };
913 CERT_ALT_NAME_ENTRY entry = { 0 };
918 /* Test with empty info */
919 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
920 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
923 ok(size == sizeof(emptyAltName), "Expected size %d, got %ld\n",
924 sizeof(emptyAltName), size);
925 ok(!memcmp(buf, emptyAltName, size), "Unexpected value\n");
928 /* Test with an empty entry */
930 info.rgAltEntry = &entry;
931 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
932 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
933 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
934 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
936 /* Test with an empty pointer */
937 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
938 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
939 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
942 ok(size == sizeof(emptyURL), "Expected size %d, got %ld\n",
943 sizeof(emptyURL), size);
944 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
947 /* Test with a real URL */
948 U(entry).pwszURL = (LPWSTR)url;
949 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
950 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
953 ok(size == sizeof(encodedURL), "Expected size %d, got %ld\n",
954 sizeof(encodedURL), size);
955 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
958 /* Now with the URL containing an invalid IA5 char */
959 U(entry).pwszURL = (LPWSTR)nihongoURL;
960 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
961 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
962 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
963 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
964 /* The first invalid character is at index 7 */
965 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
966 "Expected invalid char at index 7, got %ld\n",
967 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
968 /* Now with the URL missing a scheme */
969 U(entry).pwszURL = (LPWSTR)dnsName;
970 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
971 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
972 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
975 /* This succeeds, but it shouldn't, so don't worry about conforming */
978 /* Now with a DNS name */
979 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
980 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
981 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
982 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
985 ok(size == sizeof(encodedDnsName), "Expected size %d, got %ld\n",
986 sizeof(encodedDnsName), size);
987 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
990 /* Test with an IP address */
991 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
992 U(entry).IPAddress.cbData = sizeof(localhost);
993 U(entry).IPAddress.pbData = (LPBYTE)localhost;
994 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
995 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
998 ok(size == sizeof(encodedIPAddr), "Expected size %d, got %ld\n",
999 sizeof(encodedIPAddr), size);
1000 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1005 static void test_decodeAltName(DWORD dwEncoding)
1007 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1009 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1014 CERT_ALT_NAME_INFO *info;
1016 /* Test some bogus ones first */
1017 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1018 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1019 NULL, (BYTE *)&buf, &bufSize);
1020 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1021 "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1022 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1023 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1025 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1026 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1027 /* Now expected cases */
1028 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyAltName,
1029 emptyAltName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1031 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1034 info = (CERT_ALT_NAME_INFO *)buf;
1036 ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1040 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1041 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1043 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1046 info = (CERT_ALT_NAME_INFO *)buf;
1048 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1050 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1051 "Expected CERT_ALT_NAME_URL, got %ld\n",
1052 info->rgAltEntry[0].dwAltNameChoice);
1053 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1054 "Expected empty URL\n");
1057 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1058 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1060 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1063 info = (CERT_ALT_NAME_INFO *)buf;
1065 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1067 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1068 "Expected CERT_ALT_NAME_URL, got %ld\n",
1069 info->rgAltEntry[0].dwAltNameChoice);
1070 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1073 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1074 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1076 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1079 info = (CERT_ALT_NAME_INFO *)buf;
1081 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1083 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1084 "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1085 info->rgAltEntry[0].dwAltNameChoice);
1086 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1087 "Unexpected DNS name\n");
1090 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1091 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1093 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1096 info = (CERT_ALT_NAME_INFO *)buf;
1098 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1100 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1101 "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1102 info->rgAltEntry[0].dwAltNameChoice);
1103 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1104 "Unexpected IP address length %ld\n",
1105 U(info->rgAltEntry[0]).IPAddress.cbData);
1106 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1107 sizeof(localhost)), "Unexpected IP address value\n");
1112 struct encodedOctets
1115 const BYTE *encoded;
1118 static const struct encodedOctets octets[] = {
1119 { "hi", "\x04\x02hi" },
1120 { "somelong\xffstring", "\x04\x0fsomelong\xffstring" },
1124 static void test_encodeOctets(DWORD dwEncoding)
1126 CRYPT_DATA_BLOB blob;
1129 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1135 blob.cbData = strlen(octets[i].val);
1136 blob.pbData = (BYTE *)octets[i].val;
1137 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1138 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1139 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1143 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1144 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1145 buf[1], octets[i].encoded[1]);
1146 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1147 octets[i].encoded[1] + 1), "Got unexpected value\n");
1153 static void test_decodeOctets(DWORD dwEncoding)
1157 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1163 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1164 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1165 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1166 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1167 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1168 "Expected size >= %d, got %ld\n",
1169 sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1170 ok(buf != NULL, "Expected allocated buffer\n");
1173 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1176 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1177 "Unexpected value\n");
1183 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1188 const BYTE *encoded;
1190 const BYTE *decoded;
1193 static const struct encodedBits bits[] = {
1194 /* normal test cases */
1195 { 0, "\x03\x03\x00\xff\xff", 2, "\xff\xff" },
1196 { 1, "\x03\x03\x01\xff\xfe", 2, "\xff\xfe" },
1197 /* strange test case, showing cUnusedBits >= 8 is allowed */
1198 { 9, "\x03\x02\x01\xfe", 1, "\xfe" },
1199 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1200 { 17, "\x03\x01\x00", 0, NULL },
1203 static void test_encodeBits(DWORD dwEncoding)
1207 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1209 CRYPT_BIT_BLOB blob;
1214 blob.cbData = sizeof(bytesToEncode);
1215 blob.pbData = (BYTE *)bytesToEncode;
1216 blob.cUnusedBits = bits[i].cUnusedBits;
1217 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1218 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1219 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1222 ok(bufSize == bits[i].encoded[1] + 2,
1223 "Got unexpected size %ld, expected %d\n", bufSize,
1224 bits[i].encoded[1] + 2);
1225 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1226 "Unexpected value\n");
1232 static void test_decodeBits(DWORD dwEncoding)
1234 static const BYTE ber[] = "\x03\x02\x01\xff";
1235 static const BYTE berDecoded = 0xfe;
1242 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1244 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1245 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1247 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1250 CRYPT_BIT_BLOB *blob;
1252 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1253 "Got unexpected size %ld, expected >= %ld\n", bufSize,
1254 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1255 blob = (CRYPT_BIT_BLOB *)buf;
1256 ok(blob->cbData == bits[i].cbDecoded,
1257 "Got unexpected length %ld, expected %ld\n", blob->cbData,
1259 if (blob->cbData && bits[i].cbDecoded)
1260 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1261 "Unexpected value\n");
1265 /* special case: check that something that's valid in BER but not in DER
1266 * decodes successfully
1268 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1269 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1270 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1273 CRYPT_BIT_BLOB *blob;
1275 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1276 "Got unexpected size %ld, expected >= %d\n", bufSize,
1277 sizeof(CRYPT_BIT_BLOB) + berDecoded);
1278 blob = (CRYPT_BIT_BLOB *)buf;
1279 ok(blob->cbData == sizeof(berDecoded),
1280 "Got unexpected length %ld, expected %d\n", blob->cbData,
1281 sizeof(berDecoded));
1283 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1290 CERT_BASIC_CONSTRAINTS2_INFO info;
1291 const BYTE *encoded;
1294 static const struct Constraints2 constraints2[] = {
1295 /* empty constraints */
1296 { { FALSE, FALSE, 0}, "\x30\x00" },
1298 { { TRUE, FALSE, 0}, "\x30\x03\x01\x01\xff" },
1299 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1300 * but that's not the case
1302 { { FALSE, TRUE, 0}, "\x30\x03\x02\x01\x00" },
1303 /* can be a CA and has path length constraints set */
1304 { { TRUE, TRUE, 1}, "\x30\x06\x01\x01\xff\x02\x01\x01" },
1307 static void test_encodeBasicConstraints(DWORD dwEncoding)
1311 /* First test with the simpler info2 */
1312 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1318 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1319 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1321 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1324 ok(bufSize == constraints2[i].encoded[1] + 2,
1325 "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1327 ok(!memcmp(buf, constraints2[i].encoded,
1328 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1334 static void test_decodeBasicConstraints(DWORD dwEncoding)
1336 static const BYTE inverted[] = "\x30\x06\x02\x01\x01\x01\x01\xff";
1337 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 },
1338 "\x30\x06\x01\x01\x01\x02\x01\x01" };
1344 /* First test with simpler info2 */
1345 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1347 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1348 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1349 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1350 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1353 CERT_BASIC_CONSTRAINTS2_INFO *info =
1354 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1356 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1357 "Unexpected value\n");
1361 /* Check with the order of encoded elements inverted */
1363 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1364 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1366 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1367 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1368 ok(!buf, "Expected buf to be set to NULL\n");
1369 /* Check with a non-DER bool */
1370 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1371 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1372 (BYTE *)&buf, &bufSize);
1373 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1376 CERT_BASIC_CONSTRAINTS2_INFO *info =
1377 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1379 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1382 /* Check with a non-basic constraints value */
1383 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1384 names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1385 (BYTE *)&buf, &bufSize);
1386 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1387 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1390 /* These are terrible public keys of course, I'm just testing encoding */
1391 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1392 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1394 struct EncodedRSAPubKey
1396 const BYTE *modulus;
1398 const BYTE *encoded;
1399 size_t decodedModulusLen;
1402 struct EncodedRSAPubKey rsaPubKeys[] = {
1403 { modulus1, sizeof(modulus1),
1404 "\x30\x0f\x02\x08\x01\x01\x01\x01\x01\x00\x00\x00\x02\x03\x01\x00\x01",
1406 { modulus2, sizeof(modulus2),
1407 "\x30\x0c\x02\x05\x01\x01\x01\x01\x01\x02\x03\x01\x00\x01",
1411 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1413 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1414 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1415 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1420 /* Try with a bogus blob type */
1422 hdr->bVersion = CUR_BLOB_VERSION;
1424 hdr->aiKeyAlg = CALG_RSA_KEYX;
1425 rsaPubKey->magic = 0x31415352;
1426 rsaPubKey->bitlen = sizeof(modulus1) * 8;
1427 rsaPubKey->pubexp = 65537;
1428 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1431 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1432 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1434 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1435 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1437 /* Now with a bogus reserved field */
1438 hdr->bType = PUBLICKEYBLOB;
1440 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1441 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1445 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1446 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1447 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1450 /* Now with a bogus blob version */
1453 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1454 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1458 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1459 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1460 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1463 /* And with a bogus alg ID */
1464 hdr->bVersion = CUR_BLOB_VERSION;
1465 hdr->aiKeyAlg = CALG_DES;
1466 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1467 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1471 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1472 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1473 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1476 /* Finally, all valid, but change the modulus */
1477 hdr->aiKeyAlg = CALG_RSA_KEYX;
1478 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus2,
1480 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1481 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1485 ok(bufSize == rsaPubKeys[1].encoded[1] + 2,
1486 "Expected size %d, got %ld\n", rsaPubKeys[1].encoded[1] + 2, bufSize);
1487 ok(!memcmp(buf, rsaPubKeys[1].encoded, bufSize), "Unexpected value\n");
1492 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1499 /* Try with a bad length */
1500 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1501 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1502 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1503 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1504 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1505 /* Now try success cases */
1506 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1509 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1510 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
1511 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1512 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1515 BLOBHEADER *hdr = (BLOBHEADER *)buf;
1516 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
1518 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1519 rsaPubKeys[i].decodedModulusLen,
1520 "Expected size at least %d, got %ld\n",
1521 sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1522 rsaPubKeys[i].decodedModulusLen, bufSize);
1523 ok(hdr->bType == PUBLICKEYBLOB,
1524 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
1526 ok(hdr->bVersion == CUR_BLOB_VERSION,
1527 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
1528 CUR_BLOB_VERSION, hdr->bVersion);
1529 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
1531 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
1532 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
1533 ok(rsaPubKey->magic == 0x31415352,
1534 "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
1535 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
1536 "Expected bit len %d, got %ld\n",
1537 rsaPubKeys[i].decodedModulusLen * 8, rsaPubKey->bitlen);
1538 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
1540 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1541 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
1542 "Unexpected modulus\n");
1548 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1549 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1550 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1552 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1553 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1554 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1555 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1557 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1559 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1560 CRYPT_SEQUENCE_OF_ANY seq;
1566 /* Encode a homogenous sequence */
1567 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1569 blobs[i].cbData = ints[i].encoded[1] + 2;
1570 blobs[i].pbData = (BYTE *)ints[i].encoded;
1572 seq.cValue = sizeof(ints) / sizeof(ints[0]);
1573 seq.rgValue = blobs;
1575 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1576 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1577 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1580 ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1581 sizeof(intSequence), bufSize);
1582 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1585 /* Change the type of the first element in the sequence, and give it
1588 blobs[0].cbData = times[0].encodedTime[1] + 2;
1589 blobs[0].pbData = (BYTE *)times[0].encodedTime;
1590 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1591 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1592 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1595 ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1596 sizeof(mixedSequence), bufSize);
1597 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1598 "Unexpected value\n");
1603 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1609 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1610 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1611 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1614 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1617 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1618 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1620 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1622 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1623 "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1624 seq->rgValue[i].cbData);
1625 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1626 ints[i].encoded[1] + 2), "Unexpected value\n");
1630 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1631 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1633 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1636 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1638 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1639 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1641 /* Just check the first element since it's all that changed */
1642 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1643 "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1644 seq->rgValue[0].cbData);
1645 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1646 times[0].encodedTime[1] + 2), "Unexpected value\n");
1651 struct encodedExtensions
1653 CERT_EXTENSIONS exts;
1654 const BYTE *encoded;
1657 static CERT_EXTENSION criticalExt =
1658 { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1659 static CERT_EXTENSION nonCriticalExt =
1660 { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1662 static const struct encodedExtensions exts[] = {
1663 { { 0, NULL }, "\x30\x00" },
1664 { { 1, &criticalExt }, "\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff"
1665 "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1666 { { 1, &nonCriticalExt }, "\x30\x11\x30\x0f\x06\x03\x55\x1d\x13"
1667 "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1670 static void test_encodeExtensions(DWORD dwEncoding)
1674 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1680 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1682 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1685 ok(bufSize == exts[i].encoded[1] + 2,
1686 "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1687 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1688 "Unexpected value\n");
1694 static void test_decodeExtensions(DWORD dwEncoding)
1698 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1704 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1705 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1706 NULL, (BYTE *)&buf, &bufSize);
1707 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1710 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1713 ok(ext->cExtension == exts[i].exts.cExtension,
1714 "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1716 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1718 ok(!strcmp(ext->rgExtension[j].pszObjId,
1719 exts[i].exts.rgExtension[j].pszObjId),
1720 "Expected OID %s, got %s\n",
1721 exts[i].exts.rgExtension[j].pszObjId,
1722 ext->rgExtension[j].pszObjId);
1723 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1724 exts[i].exts.rgExtension[j].Value.pbData,
1725 exts[i].exts.rgExtension[j].Value.cbData),
1726 "Unexpected value\n");
1733 /* MS encodes public key info with a NULL if the algorithm identifier's
1734 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
1735 * it encodes them by omitting the algorithm parameters. This latter approach
1736 * seems more correct, so accept either form.
1738 struct encodedPublicKey
1740 CERT_PUBLIC_KEY_INFO info;
1741 const BYTE *encoded;
1742 const BYTE *encodedNoNull;
1743 CERT_PUBLIC_KEY_INFO decoded;
1746 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1748 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1750 static const struct encodedPublicKey pubKeys[] = {
1751 /* with a bogus OID */
1752 { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
1753 "\x30\x0b\x30\x06\x06\x02\x2a\x03\x05\x00\x03\x01\x00",
1754 "\x30\x09\x30\x04\x06\x02\x2a\x03\x03\x01\x00",
1755 { { "1.2.3", { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
1756 /* some normal keys */
1757 { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
1758 "\x30\x0f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x01\x00",
1759 "\x30\x0d\x30\x08\x06\x06\x2a\x86\x48\x86\xf7\x0d\x03\x01\x00",
1760 { { szOID_RSA, { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
1761 { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
1762 "\x30\x1f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x11\x00\x00\x01"
1763 "\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1764 "\x30\x1d\x30\x08\x06\x06\x2a\x86\x48\x86\xf7\x0d\x03\x11\x00\x00\x01"
1765 "\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1766 { { szOID_RSA, { 2, "\x05\x00" } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
1767 /* with add'l parameters--note they must be DER-encoded */
1768 { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1769 (BYTE *)aKey, 0 } },
1770 "\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
1771 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1773 "\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
1774 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1776 { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1777 (BYTE *)aKey, 0 } } },
1780 static void test_encodePublicKeyInfo(DWORD dwEncoding)
1784 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1790 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1791 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1793 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1796 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
1797 bufSize == pubKeys[i].encodedNoNull[1] + 2,
1798 "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
1799 pubKeys[i].encodedNoNull[1] + 2, bufSize);
1800 if (bufSize == pubKeys[i].encoded[1] + 2)
1801 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
1802 "Unexpected value\n");
1803 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
1804 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
1805 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
1811 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
1812 const CERT_PUBLIC_KEY_INFO *got)
1814 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
1815 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
1816 got->Algorithm.pszObjId);
1817 ok(expected->Algorithm.Parameters.cbData ==
1818 got->Algorithm.Parameters.cbData,
1819 "Expected parameters of %ld bytes, got %ld\n",
1820 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
1821 if (expected->Algorithm.Parameters.cbData)
1822 ok(!memcmp(expected->Algorithm.Parameters.pbData,
1823 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
1824 "Unexpected algorithm parameters\n");
1825 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
1826 "Expected public key of %ld bytes, got %ld\n",
1827 expected->PublicKey.cbData, got->PublicKey.cbData);
1828 if (expected->PublicKey.cbData)
1829 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
1830 got->PublicKey.cbData), "Unexpected public key value\n");
1833 static void test_decodePublicKeyInfo(DWORD dwEncoding)
1835 static const BYTE bogusPubKeyInfo[] =
1836 "\x30\x22\x30\x0d\x06\x06\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x01\x01"
1837 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1844 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1846 /* The NULL form decodes to the decoded member */
1847 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1848 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1849 NULL, (BYTE *)&buf, &bufSize);
1850 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1853 comparePublicKeyInfo(&pubKeys[i].decoded,
1854 (CERT_PUBLIC_KEY_INFO *)buf);
1857 /* The non-NULL form decodes to the original */
1858 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1859 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
1860 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1861 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1864 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
1868 /* Test with bogus (not valid DER) parameters */
1869 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1870 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1871 NULL, (BYTE *)&buf, &bufSize);
1872 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1873 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1876 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
1877 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1878 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
1879 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
1880 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1881 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
1882 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1883 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
1884 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1885 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1886 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1887 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1888 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
1889 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1890 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1891 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
1892 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
1893 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
1894 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1895 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
1896 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1897 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1898 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
1899 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
1900 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
1901 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1902 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
1903 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1904 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1905 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
1906 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
1907 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
1908 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
1909 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
1910 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
1911 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
1912 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
1913 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
1914 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1916 /* This is the encoded form of the printable string "Juan Lang" */
1917 static const BYTE encodedCommonName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11,
1918 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c,
1919 0x61, 0x6e, 0x67, 0x00 };
1920 static const BYTE serialNum[] = { 0x01 };
1922 static void test_encodeCertToBeSigned(DWORD dwEncoding)
1927 CERT_INFO info = { 0 };
1929 /* Test with NULL pvStructInfo */
1930 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
1931 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1932 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1933 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1934 /* Test with a V1 cert */
1935 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1936 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1937 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1940 ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
1941 v1Cert[1] + 2, size);
1942 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
1946 info.dwVersion = CERT_V2;
1947 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1948 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1949 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1952 ok(size == sizeof(v2Cert), "Expected size %d, got %ld\n",
1953 sizeof(v2Cert), size);
1954 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
1958 info.dwVersion = CERT_V3;
1959 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1960 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1961 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1964 ok(size == sizeof(v3Cert), "Expected size %d, got %ld\n",
1965 sizeof(v3Cert), size);
1966 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
1969 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
1970 * API doesn't prevent it)
1972 info.dwVersion = CERT_V1;
1973 info.cExtension = 1;
1974 info.rgExtension = &criticalExt;
1975 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1976 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1977 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1980 ok(size == sizeof(v1CertWithConstraints), "Expected size %d, got %ld\n",
1981 sizeof(v1CertWithConstraints), size);
1982 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
1985 /* test v1 cert with a serial number */
1986 info.SerialNumber.cbData = sizeof(serialNum);
1987 info.SerialNumber.pbData = (BYTE *)serialNum;
1988 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1989 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1992 ok(size == sizeof(v1CertWithSerial), "Expected size %d, got %ld\n",
1993 sizeof(v1CertWithSerial), size);
1994 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
1997 /* Test v1 cert with an issuer name, a subject name, and a serial number */
1998 info.Issuer.cbData = sizeof(encodedCommonName);
1999 info.Issuer.pbData = (BYTE *)encodedCommonName;
2000 info.Subject.cbData = sizeof(encodedCommonName);
2001 info.Subject.pbData = (BYTE *)encodedCommonName;
2002 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2003 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2006 ok(size == sizeof(bigCert), "Expected size %d, got %ld\n",
2007 sizeof(bigCert), size);
2008 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2011 /* for now, I let more interesting tests be done for each subcomponent,
2012 * rather than retesting them all here.
2016 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2018 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2019 v1CertWithConstraints, v1CertWithSerial };
2024 /* Test with NULL pbEncoded */
2025 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2026 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2027 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2028 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2029 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2030 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2031 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2032 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2033 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2034 * minimum a cert must have a non-zero serial number, an issuer, and a
2037 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2039 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2040 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2041 (BYTE *)&buf, &size);
2042 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2043 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2045 /* Now check with serial number, subject and issuer specified */
2046 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2047 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2048 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2051 CERT_INFO *info = (CERT_INFO *)buf;
2053 ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
2054 sizeof(CERT_INFO), size);
2055 ok(info->SerialNumber.cbData == 1,
2056 "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2057 ok(*info->SerialNumber.pbData == *serialNum,
2058 "Expected serial number %d, got %d\n", *serialNum,
2059 *info->SerialNumber.pbData);
2060 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2061 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2062 info->Issuer.cbData);
2063 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2064 "Unexpected issuer\n");
2065 ok(info->Subject.cbData == sizeof(encodedCommonName),
2066 "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
2067 info->Subject.cbData);
2068 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2069 info->Subject.cbData), "Unexpected subject\n");
2074 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2077 static const BYTE signedBigCert[] = {
2078 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2079 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2080 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2081 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2082 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2083 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2084 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2085 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2086 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2087 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2088 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2089 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2091 static void test_encodeCert(DWORD dwEncoding)
2093 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2094 * also that bigCert is a NULL-terminated string, so don't count its
2095 * last byte (otherwise the signed cert won't decode.)
2097 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2098 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2103 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2104 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2105 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2108 ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
2109 sizeof(signedBigCert), bufSize);
2110 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2115 static void test_decodeCert(DWORD dwEncoding)
2121 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2122 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2123 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2126 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2128 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2129 "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert),
2130 info->ToBeSigned.cbData);
2131 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2132 "Unexpected cert\n");
2133 ok(info->Signature.cbData == sizeof(hash),
2134 "Expected signature size %d, got %ld\n", sizeof(hash),
2135 info->Signature.cbData);
2136 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2137 "Unexpected signature\n");
2142 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
2143 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2145 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2146 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
2147 0x30, 0x30, 0x30, 0x30, 0x5a };
2148 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
2149 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
2150 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
2151 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2153 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
2154 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2155 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2156 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2157 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
2158 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2159 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
2160 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2161 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
2162 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2163 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
2164 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2165 static const BYTE v1CRLWithExt[] = { 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x30,
2166 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2167 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 0x36,
2168 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2169 0x30, 0x2c, 0x30, 0x2a, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2170 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14,
2171 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2172 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2174 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
2179 CRL_INFO info = { 0 };
2180 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
2182 /* Test with a V1 CRL */
2183 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2184 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2185 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2188 ok(size == sizeof(v1CRL), "Expected size %d, got %ld\n",
2189 sizeof(v1CRL), size);
2190 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
2194 info.dwVersion = CRL_V2;
2195 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2196 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2197 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2200 ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
2201 v2CRL[1] + 2, size);
2202 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
2205 /* v1 CRL with a name */
2206 info.dwVersion = CRL_V1;
2207 info.Issuer.cbData = sizeof(encodedCommonName);
2208 info.Issuer.pbData = (BYTE *)encodedCommonName;
2209 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2210 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2211 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2214 ok(size == sizeof(v1CRLWithIssuer), "Expected size %d, got %ld\n",
2215 sizeof(v1CRLWithIssuer), size);
2216 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
2219 /* v1 CRL with a name and a NULL entry pointer */
2221 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2222 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2223 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2224 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2225 /* now set an empty entry */
2226 info.rgCRLEntry = &entry;
2227 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2228 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2231 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2232 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEmptyEntry),
2234 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2235 "Got unexpected value\n");
2238 /* an entry with a serial number */
2239 entry.SerialNumber.cbData = sizeof(serialNum);
2240 entry.SerialNumber.pbData = (BYTE *)serialNum;
2241 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2242 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2245 ok(size == sizeof(v1CRLWithIssuerAndEntry),
2246 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEntry), size);
2247 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2248 "Got unexpected value\n");
2251 /* and finally, an entry with an extension */
2252 entry.cExtension = 1;
2253 entry.rgExtension = &criticalExt;
2254 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2255 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2256 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2259 ok(size == sizeof(v1CRLWithExt), "Expected size %d, got %ld\n",
2260 sizeof(v1CRLWithExt), size);
2261 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2266 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
2268 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
2273 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
2275 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2276 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2277 (BYTE *)&buf, &size);
2278 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2279 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2281 /* at a minimum, a CRL must contain an issuer: */
2282 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2283 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2284 (BYTE *)&buf, &size);
2285 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2288 CRL_INFO *info = (CRL_INFO *)buf;
2290 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2291 sizeof(CRL_INFO), size);
2292 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
2294 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2295 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2296 info->Issuer.cbData);
2297 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2298 "Unexpected issuer\n");
2301 /* check decoding with an empty CRL entry */
2302 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2303 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
2304 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2305 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2306 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2307 /* with a real CRL entry */
2308 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2309 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
2310 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2311 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2314 CRL_INFO *info = (CRL_INFO *)buf;
2317 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2318 sizeof(CRL_INFO), size);
2319 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2321 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2322 entry = info->rgCRLEntry;
2323 ok(entry->SerialNumber.cbData == 1,
2324 "Expected serial number size 1, got %ld\n",
2325 entry->SerialNumber.cbData);
2326 ok(*entry->SerialNumber.pbData == *serialNum,
2327 "Expected serial number %d, got %d\n", *serialNum,
2328 *entry->SerialNumber.pbData);
2329 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2330 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2331 info->Issuer.cbData);
2332 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2333 "Unexpected issuer\n");
2335 /* and finally, with an extension */
2336 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2337 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2338 NULL, (BYTE *)&buf, &size);
2339 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2342 CRL_INFO *info = (CRL_INFO *)buf;
2345 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2346 sizeof(CRL_INFO), size);
2347 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2349 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2350 entry = info->rgCRLEntry;
2351 ok(entry->SerialNumber.cbData == 1,
2352 "Expected serial number size 1, got %ld\n",
2353 entry->SerialNumber.cbData);
2354 ok(*entry->SerialNumber.pbData == *serialNum,
2355 "Expected serial number %d, got %d\n", *serialNum,
2356 *entry->SerialNumber.pbData);
2357 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2358 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2359 info->Issuer.cbData);
2360 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2361 "Unexpected issuer\n");
2362 /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2363 * bug, or am I missing something?
2365 ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2370 static void test_registerOIDFunction(void)
2372 static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
2375 /* oddly, this succeeds under WinXP; the function name key is merely
2376 * omitted. This may be a side effect of the registry code, I don't know.
2377 * I don't check it because I doubt anyone would depend on it.
2378 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
2379 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2381 /* On windows XP, GetLastError is incorrectly being set with an HRESULT,
2382 * HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)
2384 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
2386 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
2387 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)),
2388 "Expected ERROR_INVALID_PARAMETER: %ld\n", GetLastError());
2389 /* This has no effect, but "succeeds" on XP */
2390 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
2391 "1.2.3.4.5.6.7.8.9.10", NULL, NULL);
2392 ok(ret, "Expected pseudo-success, got %ld\n", GetLastError());
2393 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
2394 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2395 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2396 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
2397 "1.2.3.4.5.6.7.8.9.10");
2398 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2399 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
2400 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2401 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2402 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
2403 "1.2.3.4.5.6.7.8.9.10");
2404 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2405 /* This has no effect */
2406 ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
2407 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2408 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2409 /* Check with bogus encoding type: */
2410 ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
2411 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2412 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2413 /* This is written with value 3 verbatim. Thus, the encoding type isn't
2414 * (for now) treated as a mask.
2416 ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
2417 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2418 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2419 ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
2420 "1.2.3.4.5.6.7.8.9.10");
2421 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2426 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
2427 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
2430 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
2432 test_encodeInt(encodings[i]);
2433 test_decodeInt(encodings[i]);
2434 test_encodeEnumerated(encodings[i]);
2435 test_decodeEnumerated(encodings[i]);
2436 test_encodeFiletime(encodings[i]);
2437 test_decodeFiletime(encodings[i]);
2438 test_encodeName(encodings[i]);
2439 test_decodeName(encodings[i]);
2440 test_encodeAltName(encodings[i]);
2441 test_decodeAltName(encodings[i]);
2442 test_encodeOctets(encodings[i]);
2443 test_decodeOctets(encodings[i]);
2444 test_encodeBits(encodings[i]);
2445 test_decodeBits(encodings[i]);
2446 test_encodeBasicConstraints(encodings[i]);
2447 test_decodeBasicConstraints(encodings[i]);
2448 test_encodeRsaPublicKey(encodings[i]);
2449 test_decodeRsaPublicKey(encodings[i]);
2450 test_encodeSequenceOfAny(encodings[i]);
2451 test_decodeSequenceOfAny(encodings[i]);
2452 test_encodeExtensions(encodings[i]);
2453 test_decodeExtensions(encodings[i]);
2454 test_encodePublicKeyInfo(encodings[i]);
2455 test_decodePublicKeyInfo(encodings[i]);
2456 test_encodeCertToBeSigned(encodings[i]);
2457 test_decodeCertToBeSigned(encodings[i]);
2458 test_encodeCert(encodings[i]);
2459 test_decodeCert(encodings[i]);
2460 test_encodeCRLToBeSigned(encodings[i]);
2461 test_decodeCRLToBeSigned(encodings[i]);
2463 test_registerOIDFunction();