More comm tests.
[wine/wine64.git] / dlls / crypt32 / tests / encode.c
blob4df3d70e2502e64cda764d34fa7f402e3146d756
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
27 #include "wine/test.h"
29 struct encodedInt
31 int val;
32 const BYTE *encoded;
35 static const struct encodedInt ints[] = {
36 { 1, "\x02\x01\x01" },
37 { 127, "\x02\x01\x7f" },
38 { 128, "\x02\x02\x00\x80" },
39 { 256, "\x02\x02\x01\x00" },
40 { -128, "\x02\x01\x80" },
41 { -129, "\x02\x02\xff\x7f" },
42 { 0xbaddf00d, "\x02\x04\xba\xdd\xf0\x0d" },
45 struct encodedBigInt
47 const BYTE *val;
48 const BYTE *encoded;
49 const BYTE *decoded;
52 static const struct encodedBigInt bigInts[] = {
53 { "\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08",
54 "\x02\x0a\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff",
55 "\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08" },
56 { "\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff\xff",
57 "\x02\x09\xff\x01\x02\x03\x04\x05\x06\x07\x08",
58 "\x08\x07\x06\x05\x04\x03\x02\x01\xff" },
61 /* Decoded is the same as original, so don't bother storing a separate copy */
62 static const struct encodedBigInt bigUInts[] = {
63 { "\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08",
64 "\x02\x0a\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff", NULL },
65 { "\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff\xff",
66 "\x02\x0c\x00\xff\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08", NULL },
69 static void test_encodeInt(DWORD dwEncoding)
71 DWORD bufSize = 0;
72 int i;
73 BOOL ret;
74 CRYPT_INTEGER_BLOB blob;
75 BYTE *buf = NULL;
77 /* CryptEncodeObjectEx with NULL bufSize crashes..
78 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
79 NULL);
81 /* check bogus encoding */
82 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
83 &bufSize);
84 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
85 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
86 /* check with NULL integer buffer. Windows XP incorrectly returns an
87 * NTSTATUS.
89 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
90 &bufSize);
91 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
92 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
93 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
95 /* encode as normal integer */
96 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
97 NULL, NULL, &bufSize);
98 ok(ret, "Expected success, got %ld\n", GetLastError());
99 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
100 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
101 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
102 if (buf)
104 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
105 buf[0]);
106 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
107 buf[1], ints[i].encoded[1]);
108 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
109 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
110 LocalFree(buf);
112 /* encode as multibyte integer */
113 blob.cbData = sizeof(ints[i].val);
114 blob.pbData = (BYTE *)&ints[i].val;
115 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
116 0, NULL, NULL, &bufSize);
117 ok(ret, "Expected success, got %ld\n", GetLastError());
118 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
119 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
120 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
121 if (buf)
123 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
124 buf[0]);
125 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
126 buf[1], ints[i].encoded[1]);
127 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
128 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
129 LocalFree(buf);
132 /* encode a couple bigger ints, just to show it's little-endian and leading
133 * sign bytes are dropped
135 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
137 blob.cbData = strlen(bigInts[i].val);
138 blob.pbData = (BYTE *)bigInts[i].val;
139 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
140 0, NULL, NULL, &bufSize);
141 ok(ret, "Expected success, got %ld\n", GetLastError());
142 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
143 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
144 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
145 if (buf)
147 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
148 buf[0]);
149 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
150 buf[1], bigInts[i].encoded[1]);
151 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
152 bigInts[i].encoded[1] + 1),
153 "Encoded value didn't match expected\n");
154 LocalFree(buf);
157 /* and, encode some uints */
158 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
160 blob.cbData = strlen(bigUInts[i].val);
161 blob.pbData = (BYTE *)bigUInts[i].val;
162 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
163 0, NULL, NULL, &bufSize);
164 ok(ret, "Expected success, got %ld\n", GetLastError());
165 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
166 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
167 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
168 if (buf)
170 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
171 buf[0]);
172 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
173 buf[1], bigUInts[i].encoded[1]);
174 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
175 bigUInts[i].encoded[1] + 1),
176 "Encoded value didn't match expected\n");
177 LocalFree(buf);
182 static void test_decodeInt(DWORD dwEncoding)
184 static const char bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
185 static const char testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
186 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
187 static const BYTE tooBig[] = { 0x02, 0x84, 0xff, 0xff, 0xff, 0xff };
188 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
189 BYTE *buf = NULL;
190 DWORD bufSize = 0;
191 int i;
192 BOOL ret;
194 /* CryptDecodeObjectEx with NULL bufSize crashes..
195 ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
196 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
198 /* check bogus encoding */
199 ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
200 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
201 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
202 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
203 /* check with NULL integer buffer */
204 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
205 &bufSize);
206 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
207 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
208 /* check with a valid, but too large, integer */
209 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
210 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
211 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
212 "Expected CRYPT_E_ASN1_LARGE, got %ld\n", GetLastError());
213 /* check with a DER-encoded string */
214 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
215 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
216 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
217 "Expected CRYPT_E_ASN1_BADTAG, got %ld\n", GetLastError());
218 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
220 /* When the output buffer is NULL, this always succeeds */
221 SetLastError(0xdeadbeef);
222 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
223 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
224 &bufSize);
225 ok(ret && GetLastError() == NOERROR,
226 "Expected success and NOERROR, got %ld\n", GetLastError());
227 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
228 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
231 ok(bufSize == sizeof(int), "Expected size %d, got %ld\n", sizeof(int),
232 bufSize);
233 ok(buf != NULL, "Expected allocated buffer\n");
234 if (buf)
236 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
237 ints[i].val, *(int *)buf);
238 LocalFree(buf);
241 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
243 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
244 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
245 &bufSize);
246 ok(ret && GetLastError() == NOERROR,
247 "Expected success and NOERROR, got %ld\n", GetLastError());
248 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
249 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
250 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
251 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
252 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
253 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
254 bufSize);
255 ok(buf != NULL, "Expected allocated buffer\n");
256 if (buf)
258 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
260 ok(blob->cbData == strlen(bigInts[i].decoded),
261 "Expected len %d, got %ld\n", strlen(bigInts[i].decoded),
262 blob->cbData);
263 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
264 "Unexpected value\n");
265 LocalFree(buf);
268 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
270 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
271 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
272 &bufSize);
273 ok(ret && GetLastError() == NOERROR,
274 "Expected success and NOERROR, got %ld\n", GetLastError());
275 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
276 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
277 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
278 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
279 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
280 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
281 bufSize);
282 ok(buf != NULL, "Expected allocated buffer\n");
283 if (buf)
285 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
287 ok(blob->cbData == strlen(bigUInts[i].val),
288 "Expected len %d, got %ld\n", strlen(bigUInts[i].val),
289 blob->cbData);
290 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
291 "Unexpected value\n");
292 LocalFree(buf);
295 /* Decode the value 1 with long-form length */
296 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
297 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
298 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
299 if (buf)
301 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
302 LocalFree(buf);
304 /* Try to decode some bogus large items */
305 /* The buffer size is smaller than the encoded length, so this should fail
306 * with CRYPT_E_ASN1_EOD if it's being decoded. It's failing with
307 * CRYPT_E_ASN1_LARGE, meaning there's a limit on the size decoded.
308 * The magic limit under XP seems to be 0x061a8000 bytes--more than this
309 * fails with CRYPT_E_ASN1_LARGE.
311 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
312 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
313 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
314 "Expected CRYPT_E_ASN1_LARGE, got %08lx\n", GetLastError());
315 /* This will try to decode the buffer and overflow it, check that it's
316 * caught.
318 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
319 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
320 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
321 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
324 /* These are always encoded unsigned, and aren't constrained to be any
325 * particular value
327 static const struct encodedInt enums[] = {
328 { 1, "\x0a\x01\x01" },
329 { -128, "\x0a\x05\x00\xff\xff\xff\x80" },
332 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
333 * X509_ENUMERATED.
335 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
336 szOID_CRL_REASON_CODE };
338 static void test_encodeEnumerated(DWORD dwEncoding)
340 DWORD i, j;
342 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
344 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
346 BOOL ret;
347 BYTE *buf = NULL;
348 DWORD bufSize = 0;
350 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
351 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
352 &bufSize);
353 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
354 if (buf)
356 ok(buf[0] == 0xa,
357 "Got unexpected type %d for enumerated (expected 0xa)\n",
358 buf[0]);
359 ok(buf[1] == enums[j].encoded[1],
360 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
361 ok(!memcmp(buf + 1, enums[j].encoded + 1,
362 enums[j].encoded[1] + 1),
363 "Encoded value of 0x%08x didn't match expected\n",
364 enums[j].val);
365 LocalFree(buf);
371 static void test_decodeEnumerated(DWORD dwEncoding)
373 DWORD i, j;
375 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
377 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
379 BOOL ret;
380 DWORD bufSize = sizeof(int);
381 int val;
383 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
384 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
385 (BYTE *)&val, &bufSize);
386 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
387 ok(bufSize == sizeof(int),
388 "Got unexpected size %ld for enumerated (expected %d)\n",
389 bufSize, sizeof(int));
390 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
391 val, enums[j].val);
396 struct encodedFiletime
398 SYSTEMTIME sysTime;
399 const BYTE *encodedTime;
402 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
403 const struct encodedFiletime *time)
405 FILETIME ft = { 0 };
406 BYTE *buf = NULL;
407 DWORD bufSize = 0;
408 BOOL ret;
410 ret = SystemTimeToFileTime(&time->sysTime, &ft);
411 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
412 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
413 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
414 /* years other than 1950-2050 are not allowed for encodings other than
415 * X509_CHOICE_OF_TIME.
417 if (structType == X509_CHOICE_OF_TIME ||
418 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
420 ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
421 GetLastError());
422 ok(buf != NULL, "Expected an allocated buffer\n");
423 if (buf)
425 ok(buf[0] == time->encodedTime[0],
426 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
427 buf[0]);
428 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %ld\n",
429 time->encodedTime[1], bufSize);
430 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
431 "Got unexpected value for time encoding\n");
432 LocalFree(buf);
435 else
436 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
437 "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
440 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
441 const struct encodedFiletime *time)
443 FILETIME ft1 = { 0 }, ft2 = { 0 };
444 DWORD size = sizeof(ft2);
445 BOOL ret;
447 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
448 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
449 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
450 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
451 /* years other than 1950-2050 are not allowed for encodings other than
452 * X509_CHOICE_OF_TIME.
454 if (structType == X509_CHOICE_OF_TIME ||
455 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
457 ok(ret, "CryptDecodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
458 GetLastError());
459 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
460 "Got unexpected value for time decoding\n");
462 else
463 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
464 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
467 static const struct encodedFiletime times[] = {
468 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, "\x17" "\x0d" "050606161000Z" },
469 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, "\x18" "\x0f" "19450606161000Z" },
470 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, "\x18" "\x0f" "21450606161000Z" },
473 static void test_encodeFiletime(DWORD dwEncoding)
475 DWORD i;
477 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
479 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
480 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
481 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
485 static void test_decodeFiletime(DWORD dwEncoding)
487 static const struct encodedFiletime otherTimes[] = {
488 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, "\x18" "\x13" "19450606161000.000Z" },
489 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, "\x18" "\x13" "19450606161000.999Z" },
490 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, "\x18" "\x13" "19450606161000+0100" },
491 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, "\x18" "\x13" "19450606161000-0100" },
492 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, "\x18" "\x13" "19450606161000-0115" },
493 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, "\x18" "\x0a" "2145060616" },
494 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, "\x17" "\x0a" "4506061610" },
495 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, "\x17" "\x0b" "4506061610Z" },
496 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, "\x17" "\x0d" "4506061610+01" },
497 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, "\x17" "\x0d" "4506061610-01" },
498 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, "\x17" "\x0f" "4506061610+0100" },
499 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, "\x17" "\x0f" "4506061610-0100" },
501 /* An oddball case that succeeds in Windows, but doesn't seem correct
502 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
504 static const char *bogusTimes[] = {
505 /* oddly, this succeeds on Windows, with year 2765
506 "\x18" "\x0f" "21r50606161000Z",
508 "\x17" "\x08" "45060616",
509 "\x18" "\x0f" "aaaaaaaaaaaaaaZ",
510 "\x18" "\x04" "2145",
511 "\x18" "\x08" "21450606",
513 DWORD i, size;
514 FILETIME ft1 = { 0 }, ft2 = { 0 };
515 BOOL ret;
517 /* Check bogus length with non-NULL buffer */
518 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
519 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
520 size = 1;
521 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
522 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
523 ok(!ret && GetLastError() == ERROR_MORE_DATA,
524 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
525 /* Normal tests */
526 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
528 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
529 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
530 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
532 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
534 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
535 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
536 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
538 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
540 size = sizeof(ft1);
541 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
542 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
543 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
544 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
548 struct EncodedName
550 CERT_RDN_ATTR attr;
551 const BYTE *encoded;
554 static const char commonName[] = "Juan Lang";
555 static const char surName[] = "Lang";
556 static const char bogusIA5[] = "\x80";
557 static const char bogusPrintable[] = "~";
558 static const char bogusNumeric[] = "A";
559 static const struct EncodedName names[] = {
560 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
561 { sizeof(commonName), (BYTE *)commonName } },
562 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0aJuan Lang" },
563 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
564 { sizeof(commonName), (BYTE *)commonName } },
565 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x16\x0aJuan Lang" },
566 { { szOID_SUR_NAME, CERT_RDN_IA5_STRING,
567 { sizeof(surName), (BYTE *)surName } },
568 "\x30\x10\x31\x0e\x30\x0c\x06\x03\x55\x04\x04\x16\x05Lang" },
569 { { NULL, CERT_RDN_PRINTABLE_STRING,
570 { sizeof(commonName), (BYTE *)commonName } },
571 "\x30\x12\x31\x10\x30\x0e\x06\x00\x13\x0aJuan Lang" },
572 /* The following test isn't a very good one, because it doesn't encode any
573 * Japanese characters. I'm leaving it out for now.
574 { { szOID_COMMON_NAME, CERT_RDN_T61_STRING,
575 { sizeof(commonName), (BYTE *)commonName } },
576 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x14\x0aJuan Lang" },
578 /* The following tests succeed under Windows, but really should fail,
579 * they contain characters that are illegal for the encoding. I'm
580 * including them to justify my lazy encoding.
582 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
583 { sizeof(bogusIA5), (BYTE *)bogusIA5 } },
584 "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x16\x02\x80" },
585 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
586 { sizeof(bogusPrintable), (BYTE *)bogusPrintable } },
587 "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x13\x02\x7e" },
588 { { szOID_COMMON_NAME, CERT_RDN_NUMERIC_STRING,
589 { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
590 "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x12\x02\x41" },
593 static const BYTE emptyName[] = { 0x30, 0 };
594 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
595 static const BYTE twoRDNs[] = "\x30\x23\x31\x21\x30\x0c\x06\x03\x55\x04\x04"
596 "\x13\x05\x4c\x61\x6e\x67\x00\x30\x11\x06\x03\x55\x04\x03"
597 "\x13\x0a\x4a\x75\x61\x6e\x20\x4c\x61\x6e\x67";
599 static void test_encodeName(DWORD dwEncoding)
601 CERT_RDN_ATTR attrs[2];
602 CERT_RDN rdn;
603 CERT_NAME_INFO info;
604 BYTE *buf = NULL;
605 DWORD size = 0, i;
606 BOOL ret;
608 /* Test with NULL pvStructInfo */
609 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
610 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
611 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
612 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
613 /* Test with empty CERT_NAME_INFO */
614 info.cRDN = 0;
615 info.rgRDN = NULL;
616 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
617 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
618 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
619 if (buf)
621 ok(!memcmp(buf, emptyName, sizeof(emptyName)),
622 "Got unexpected encoding for empty name\n");
623 LocalFree(buf);
625 /* Test with bogus CERT_RDN */
626 info.cRDN = 1;
627 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
628 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
629 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
630 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
631 /* Test with empty CERT_RDN */
632 rdn.cRDNAttr = 0;
633 rdn.rgRDNAttr = NULL;
634 info.cRDN = 1;
635 info.rgRDN = &rdn;
636 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
637 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
638 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
639 if (buf)
641 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
642 "Got unexpected encoding for empty RDN array\n");
643 LocalFree(buf);
645 /* Test with bogus attr array */
646 rdn.cRDNAttr = 1;
647 rdn.rgRDNAttr = NULL;
648 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
649 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
650 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
651 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
652 /* oddly, a bogus OID is accepted by Windows XP; not testing.
653 attrs[0].pszObjId = "bogus";
654 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
655 attrs[0].Value.cbData = sizeof(commonName);
656 attrs[0].Value.pbData = (BYTE *)commonName;
657 rdn.cRDNAttr = 1;
658 rdn.rgRDNAttr = attrs;
659 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
660 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
661 ok(!ret, "Expected failure, got success\n");
663 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
664 * the encoded attributes to be swapped.
666 attrs[0].pszObjId = szOID_COMMON_NAME;
667 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
668 attrs[0].Value.cbData = sizeof(commonName);
669 attrs[0].Value.pbData = (BYTE *)commonName;
670 attrs[1].pszObjId = szOID_SUR_NAME;
671 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
672 attrs[1].Value.cbData = sizeof(surName);
673 attrs[1].Value.pbData = (BYTE *)surName;
674 rdn.cRDNAttr = 2;
675 rdn.rgRDNAttr = attrs;
676 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
677 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
678 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
679 if (buf)
681 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
682 "Got unexpected encoding for two RDN array\n");
683 LocalFree(buf);
685 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
686 rdn.cRDNAttr = 1;
687 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
688 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
689 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
690 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
691 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
692 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
694 rdn.cRDNAttr = 1;
695 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
696 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
697 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
698 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
699 if (buf)
701 ok(size == names[i].encoded[1] + 2, "Expected size %d, got %ld\n",
702 names[i].encoded[1] + 2, size);
703 ok(!memcmp(buf, names[i].encoded, names[i].encoded[1] + 2),
704 "Got unexpected encoding\n");
705 LocalFree(buf);
710 static void compareNames(const CERT_NAME_INFO *expected,
711 const CERT_NAME_INFO *got)
713 ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
714 expected->cRDN, got->cRDN);
715 if (expected->cRDN)
717 ok(got->rgRDN[0].cRDNAttr == expected->rgRDN[0].cRDNAttr,
718 "Expected %ld RDN attrs, got %ld\n", expected->rgRDN[0].cRDNAttr,
719 got->rgRDN[0].cRDNAttr);
720 if (expected->rgRDN[0].cRDNAttr)
722 if (expected->rgRDN[0].rgRDNAttr[0].pszObjId &&
723 strlen(expected->rgRDN[0].rgRDNAttr[0].pszObjId))
725 ok(got->rgRDN[0].rgRDNAttr[0].pszObjId != NULL,
726 "Expected OID %s, got NULL\n",
727 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
728 if (got->rgRDN[0].rgRDNAttr[0].pszObjId)
729 ok(!strcmp(got->rgRDN[0].rgRDNAttr[0].pszObjId,
730 expected->rgRDN[0].rgRDNAttr[0].pszObjId),
731 "Got unexpected OID %s, expected %s\n",
732 got->rgRDN[0].rgRDNAttr[0].pszObjId,
733 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
735 ok(got->rgRDN[0].rgRDNAttr[0].Value.cbData ==
736 expected->rgRDN[0].rgRDNAttr[0].Value.cbData,
737 "Unexpected data size, got %ld, expected %ld\n",
738 got->rgRDN[0].rgRDNAttr[0].Value.cbData,
739 expected->rgRDN[0].rgRDNAttr[0].Value.cbData);
740 if (expected->rgRDN[0].rgRDNAttr[0].Value.pbData)
741 ok(!memcmp(got->rgRDN[0].rgRDNAttr[0].Value.pbData,
742 expected->rgRDN[0].rgRDNAttr[0].Value.pbData,
743 expected->rgRDN[0].rgRDNAttr[0].Value.cbData),
744 "Unexpected value\n");
749 static void test_decodeName(DWORD dwEncoding)
751 int i;
752 BYTE *buf = NULL;
753 DWORD bufSize = 0;
754 BOOL ret;
755 CERT_RDN rdn;
756 CERT_NAME_INFO info = { 1, &rdn };
758 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
760 /* When the output buffer is NULL, this always succeeds */
761 SetLastError(0xdeadbeef);
762 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
763 names[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
764 ok(ret && GetLastError() == NOERROR,
765 "Expected success and NOERROR, got %08lx\n", GetLastError());
766 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
767 names[i].encoded[1] + 2,
768 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
769 (BYTE *)&buf, &bufSize);
770 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
771 rdn.cRDNAttr = 1;
772 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
773 if (buf)
775 compareNames((CERT_NAME_INFO *)buf, &info);
776 LocalFree(buf);
779 /* test empty name */
780 bufSize = 0;
781 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyName,
782 emptyName[1] + 2,
783 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
784 (BYTE *)&buf, &bufSize);
785 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
786 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
787 * decoder works the same way, so only test the count.
789 if (buf)
791 ok(bufSize == sizeof(CERT_NAME_INFO),
792 "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
793 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
794 "Expected 0 RDNs in empty info, got %ld\n",
795 ((CERT_NAME_INFO *)buf)->cRDN);
796 LocalFree(buf);
798 /* test empty RDN */
799 bufSize = 0;
800 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
801 emptyRDNs[1] + 2,
802 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
803 (BYTE *)&buf, &bufSize);
804 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
805 if (buf)
807 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
809 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
810 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
811 "Got unexpected value for empty RDN\n");
812 LocalFree(buf);
814 /* test two RDN attrs */
815 bufSize = 0;
816 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
817 twoRDNs[1] + 2,
818 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
819 (BYTE *)&buf, &bufSize);
820 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
821 if (buf)
823 CERT_RDN_ATTR attrs[] = {
824 { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
825 (BYTE *)surName } },
826 { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
827 (BYTE *)commonName } },
830 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
831 rdn.rgRDNAttr = attrs;
832 compareNames((CERT_NAME_INFO *)buf, &info);
833 LocalFree(buf);
837 struct encodedOctets
839 const BYTE *val;
840 const BYTE *encoded;
843 static const struct encodedOctets octets[] = {
844 { "hi", "\x04\x02hi" },
845 { "somelong\xffstring", "\x04\x0fsomelong\xffstring" },
846 { "", "\x04\x00" },
849 static void test_encodeOctets(DWORD dwEncoding)
851 CRYPT_DATA_BLOB blob;
852 DWORD i;
854 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
856 BYTE *buf = NULL;
857 BOOL ret;
858 DWORD bufSize = 0;
860 blob.cbData = strlen(octets[i].val);
861 blob.pbData = (BYTE *)octets[i].val;
862 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
863 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
864 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
865 if (buf)
867 ok(buf[0] == 4,
868 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
869 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
870 buf[1], octets[i].encoded[1]);
871 ok(!memcmp(buf + 1, octets[i].encoded + 1,
872 octets[i].encoded[1] + 1), "Got unexpected value\n");
873 LocalFree(buf);
878 static void test_decodeOctets(DWORD dwEncoding)
880 DWORD i;
882 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
884 BYTE *buf = NULL;
885 BOOL ret;
886 DWORD bufSize = 0;
888 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
889 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
890 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
891 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
892 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
893 "Expected size >= %d, got %ld\n",
894 sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
895 ok(buf != NULL, "Expected allocated buffer\n");
896 if (buf)
898 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
900 if (blob->cbData)
901 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
902 "Unexpected value\n");
903 LocalFree(buf);
908 static const BYTE bytesToEncode[] = { 0xff, 0xff };
910 struct encodedBits
912 DWORD cUnusedBits;
913 const BYTE *encoded;
914 DWORD cbDecoded;
915 const BYTE *decoded;
918 static const struct encodedBits bits[] = {
919 /* normal test cases */
920 { 0, "\x03\x03\x00\xff\xff", 2, "\xff\xff" },
921 { 1, "\x03\x03\x01\xff\xfe", 2, "\xff\xfe" },
922 /* strange test case, showing cUnusedBits >= 8 is allowed */
923 { 9, "\x03\x02\x01\xfe", 1, "\xfe" },
924 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
925 { 17, "\x03\x01\x00", 0, NULL },
928 static void test_encodeBits(DWORD dwEncoding)
930 DWORD i;
932 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
934 CRYPT_BIT_BLOB blob;
935 BOOL ret;
936 BYTE *buf = NULL;
937 DWORD bufSize = 0;
939 blob.cbData = sizeof(bytesToEncode);
940 blob.pbData = (BYTE *)bytesToEncode;
941 blob.cUnusedBits = bits[i].cUnusedBits;
942 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
943 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
944 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
945 if (buf)
947 ok(bufSize == bits[i].encoded[1] + 2,
948 "Got unexpected size %ld, expected %d\n", bufSize,
949 bits[i].encoded[1] + 2);
950 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
951 "Unexpected value\n");
952 LocalFree(buf);
957 static void test_decodeBits(DWORD dwEncoding)
959 static const BYTE ber[] = "\x03\x02\x01\xff";
960 static const BYTE berDecoded = 0xfe;
961 DWORD i;
962 BOOL ret;
963 BYTE *buf = NULL;
964 DWORD bufSize = 0;
966 /* normal cases */
967 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
969 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
970 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
971 &bufSize);
972 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
973 if (buf)
975 CRYPT_BIT_BLOB *blob;
977 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
978 "Got unexpected size %ld, expected >= %ld\n", bufSize,
979 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
980 blob = (CRYPT_BIT_BLOB *)buf;
981 ok(blob->cbData == bits[i].cbDecoded,
982 "Got unexpected length %ld, expected %ld\n", blob->cbData,
983 bits[i].cbDecoded);
984 if (blob->cbData && bits[i].cbDecoded)
985 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
986 "Unexpected value\n");
987 LocalFree(buf);
990 /* special case: check that something that's valid in BER but not in DER
991 * decodes successfully
993 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
994 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
995 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
996 if (buf)
998 CRYPT_BIT_BLOB *blob;
1000 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1001 "Got unexpected size %ld, expected >= %d\n", bufSize,
1002 sizeof(CRYPT_BIT_BLOB) + berDecoded);
1003 blob = (CRYPT_BIT_BLOB *)buf;
1004 ok(blob->cbData == sizeof(berDecoded),
1005 "Got unexpected length %ld, expected %d\n", blob->cbData,
1006 sizeof(berDecoded));
1007 if (blob->cbData)
1008 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1009 LocalFree(buf);
1013 struct Constraints2
1015 CERT_BASIC_CONSTRAINTS2_INFO info;
1016 const BYTE *encoded;
1019 static const struct Constraints2 constraints2[] = {
1020 /* empty constraints */
1021 { { FALSE, FALSE, 0}, "\x30\x00" },
1022 /* can be a CA */
1023 { { TRUE, FALSE, 0}, "\x30\x03\x01\x01\xff" },
1024 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1025 * but that's not the case
1027 { { FALSE, TRUE, 0}, "\x30\x03\x02\x01\x00" },
1028 /* can be a CA and has path length constraints set */
1029 { { TRUE, TRUE, 1}, "\x30\x06\x01\x01\xff\x02\x01\x01" },
1032 static void test_encodeBasicConstraints(DWORD dwEncoding)
1034 DWORD i;
1036 /* First test with the simpler info2 */
1037 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1039 BOOL ret;
1040 BYTE *buf = NULL;
1041 DWORD bufSize = 0;
1043 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1044 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1045 &bufSize);
1046 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1047 if (buf)
1049 ok(bufSize == constraints2[i].encoded[1] + 2,
1050 "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1051 bufSize);
1052 ok(!memcmp(buf, constraints2[i].encoded,
1053 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1054 LocalFree(buf);
1059 static void test_decodeBasicConstraints(DWORD dwEncoding)
1061 static const BYTE inverted[] = "\x30\x06\x02\x01\x01\x01\x01\xff";
1062 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 },
1063 "\x30\x06\x01\x01\x01\x02\x01\x01" };
1064 DWORD i;
1065 BOOL ret;
1066 BYTE *buf = NULL;
1067 DWORD bufSize = 0;
1069 /* First test with simpler info2 */
1070 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1072 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1073 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1074 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1075 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1076 if (buf)
1078 CERT_BASIC_CONSTRAINTS2_INFO *info =
1079 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1081 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1082 "Unexpected value\n");
1083 LocalFree(buf);
1086 /* Check with the order of encoded elements inverted */
1087 buf = (PBYTE)1;
1088 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1089 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1090 &bufSize);
1091 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1092 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1093 ok(!buf, "Expected buf to be set to NULL\n");
1094 /* Check with a non-DER bool */
1095 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1096 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1097 (BYTE *)&buf, &bufSize);
1098 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1099 if (buf)
1101 CERT_BASIC_CONSTRAINTS2_INFO *info =
1102 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1104 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1105 LocalFree(buf);
1107 /* Check with a non-basic constraints value */
1108 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1109 names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1110 (BYTE *)&buf, &bufSize);
1111 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1112 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1115 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1116 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1117 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1119 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1120 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1121 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1122 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1124 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1126 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1127 CRYPT_SEQUENCE_OF_ANY seq;
1128 DWORD i;
1129 BOOL ret;
1130 BYTE *buf = NULL;
1131 DWORD bufSize = 0;
1133 /* Encode a homogenous sequence */
1134 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1136 blobs[i].cbData = ints[i].encoded[1] + 2;
1137 blobs[i].pbData = (BYTE *)ints[i].encoded;
1139 seq.cValue = sizeof(ints) / sizeof(ints[0]);
1140 seq.rgValue = blobs;
1142 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1143 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1144 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1145 if (buf)
1147 ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1148 sizeof(intSequence), bufSize);
1149 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1150 LocalFree(buf);
1152 /* Change the type of the first element in the sequence, and give it
1153 * another go
1155 blobs[0].cbData = times[0].encodedTime[1] + 2;
1156 blobs[0].pbData = (BYTE *)times[0].encodedTime;
1157 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1158 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1159 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1160 if (buf)
1162 ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1163 sizeof(mixedSequence), bufSize);
1164 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1165 "Unexpected value\n");
1166 LocalFree(buf);
1170 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1172 BOOL ret;
1173 BYTE *buf = NULL;
1174 DWORD bufSize = 0;
1176 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1177 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1178 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1179 if (buf)
1181 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1182 DWORD i;
1184 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1185 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1186 seq->cValue);
1187 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1189 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1190 "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1191 seq->rgValue[i].cbData);
1192 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1193 ints[i].encoded[1] + 2), "Unexpected value\n");
1195 LocalFree(buf);
1197 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1198 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1199 &bufSize);
1200 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1201 if (buf)
1203 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1205 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1206 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1207 seq->cValue);
1208 /* Just check the first element since it's all that changed */
1209 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1210 "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1211 seq->rgValue[0].cbData);
1212 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1213 times[0].encodedTime[1] + 2), "Unexpected value\n");
1214 LocalFree(buf);
1218 struct encodedExtensions
1220 CERT_EXTENSIONS exts;
1221 const BYTE *encoded;
1224 static CERT_EXTENSION criticalExt =
1225 { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1226 static CERT_EXTENSION nonCriticalExt =
1227 { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1229 static const struct encodedExtensions exts[] = {
1230 { { 0, NULL }, "\x30\x00" },
1231 { { 1, &criticalExt }, "\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff"
1232 "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1233 { { 1, &nonCriticalExt }, "\x30\x11\x30\x0f\x06\x03\x55\x1d\x13"
1234 "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1237 static void test_encodeExtensions(DWORD dwEncoding)
1239 DWORD i;
1241 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1243 BOOL ret;
1244 BYTE *buf = NULL;
1245 DWORD bufSize = 0;
1247 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1248 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1249 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1250 if (buf)
1252 ok(bufSize == exts[i].encoded[1] + 2,
1253 "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1254 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1255 "Unexpected value\n");
1256 LocalFree(buf);
1261 static void test_decodeExtensions(DWORD dwEncoding)
1263 DWORD i;
1265 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1267 BOOL ret;
1268 BYTE *buf = NULL;
1269 DWORD bufSize = 0;
1271 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1272 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1273 NULL, (BYTE *)&buf, &bufSize);
1274 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1275 if (buf)
1277 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1278 DWORD j;
1280 ok(ext->cExtension == exts[i].exts.cExtension,
1281 "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1282 ext->cExtension);
1283 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1285 ok(!strcmp(ext->rgExtension[j].pszObjId,
1286 exts[i].exts.rgExtension[j].pszObjId),
1287 "Expected OID %s, got %s\n",
1288 exts[i].exts.rgExtension[j].pszObjId,
1289 ext->rgExtension[j].pszObjId);
1290 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1291 exts[i].exts.rgExtension[j].Value.pbData,
1292 exts[i].exts.rgExtension[j].Value.cbData),
1293 "Unexpected value\n");
1295 LocalFree(buf);
1300 /* MS encodes public key info with a NULL if the algorithm identifier's
1301 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
1302 * it encodes them by omitting the algorithm parameters. This latter approach
1303 * seems more correct, so accept either form.
1305 struct encodedPublicKey
1307 CERT_PUBLIC_KEY_INFO info;
1308 const BYTE *encoded;
1309 const BYTE *encodedNoNull;
1310 CERT_PUBLIC_KEY_INFO decoded;
1313 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1314 0xe, 0xf };
1315 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1317 static const struct encodedPublicKey pubKeys[] = {
1318 /* with a bogus OID */
1319 { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
1320 "\x30\x0b\x30\x06\x06\x02\x2a\x03\x05\x00\x03\x01\x00",
1321 "\x30\x09\x30\x04\x06\x02\x2a\x03\x03\x01\x00",
1322 { { "1.2.3", { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
1323 /* some normal keys */
1324 { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
1325 "\x30\x0f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x01\x00",
1326 "\x30\x0d\x30\x08\x06\x06\x2a\x86\x48\x86\xf7\x0d\x03\x01\x00",
1327 { { szOID_RSA, { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
1328 { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
1329 "\x30\x1f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x11\x00\x00\x01"
1330 "\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1331 "\x30\x1d\x30\x08\x06\x06\x2a\x86\x48\x86\xf7\x0d\x03\x11\x00\x00\x01"
1332 "\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1333 { { szOID_RSA, { 2, "\x05\x00" } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
1334 /* with add'l parameters--note they must be DER-encoded */
1335 { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1336 (BYTE *)aKey, 0 } },
1337 "\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
1338 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1339 "\x0f",
1340 "\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
1341 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1342 "\x0f",
1343 { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1344 (BYTE *)aKey, 0 } } },
1347 static void test_encodePublicKeyInfo(DWORD dwEncoding)
1349 DWORD i;
1351 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1353 BOOL ret;
1354 BYTE *buf = NULL;
1355 DWORD bufSize = 0;
1357 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1358 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1359 &bufSize);
1360 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1361 if (buf)
1363 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
1364 bufSize == pubKeys[i].encodedNoNull[1] + 2,
1365 "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
1366 pubKeys[i].encodedNoNull[1] + 2, bufSize);
1367 if (bufSize == pubKeys[i].encoded[1] + 2)
1368 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
1369 "Unexpected value\n");
1370 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
1371 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
1372 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
1373 LocalFree(buf);
1378 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
1379 const CERT_PUBLIC_KEY_INFO *got)
1381 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
1382 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
1383 got->Algorithm.pszObjId);
1384 ok(expected->Algorithm.Parameters.cbData ==
1385 got->Algorithm.Parameters.cbData,
1386 "Expected parameters of %ld bytes, got %ld\n",
1387 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
1388 if (expected->Algorithm.Parameters.cbData)
1389 ok(!memcmp(expected->Algorithm.Parameters.pbData,
1390 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
1391 "Unexpected algorithm parameters\n");
1392 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
1393 "Expected public key of %ld bytes, got %ld\n",
1394 expected->PublicKey.cbData, got->PublicKey.cbData);
1395 if (expected->PublicKey.cbData)
1396 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
1397 got->PublicKey.cbData), "Unexpected public key value\n");
1400 static void test_decodePublicKeyInfo(DWORD dwEncoding)
1402 static const BYTE bogusPubKeyInfo[] =
1403 "\x30\x22\x30\x0d\x06\x06\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x01\x01"
1404 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1405 "\x0f";
1406 DWORD i;
1407 BOOL ret;
1408 BYTE *buf = NULL;
1409 DWORD bufSize = 0;
1411 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1413 /* The NULL form decodes to the decoded member */
1414 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1415 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1416 NULL, (BYTE *)&buf, &bufSize);
1417 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1418 if (buf)
1420 comparePublicKeyInfo(&pubKeys[i].decoded,
1421 (CERT_PUBLIC_KEY_INFO *)buf);
1422 LocalFree(buf);
1424 /* The non-NULL form decodes to the original */
1425 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1426 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
1427 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1428 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1429 if (buf)
1431 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
1432 LocalFree(buf);
1435 /* Test with bogus (not valid DER) parameters */
1436 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1437 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1438 NULL, (BYTE *)&buf, &bufSize);
1439 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1440 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1443 static const BYTE v1Cert[] = "\x30\x33\x02\x00\x30\x02\x06\x00\x30\x22\x18"
1444 "\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x18\x0f\x31"
1445 "\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x07\x30\x02\x06"
1446 "\x00\x03\x01\x00";
1447 static const BYTE v2Cert[] = "\x30\x38\xa0\x03\x02\x01\x01\x02\x00\x30\x02\x06"
1448 "\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30"
1449 "\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30"
1450 "\x07\x30\x02\x06\x00\x03\x01\x00";
1451 static const BYTE v3Cert[] = "\x30\x38\xa0\x03\x02\x01\x02\x02\x00\x30\x02\x06"
1452 "\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30"
1453 "\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30"
1454 "\x07\x30\x02\x06\x00\x03\x01\x00";
1455 static const BYTE v1CertWithConstraints[] = "\x30\x4b\x02\x00\x30\x02\x06\x00"
1456 "\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a"
1457 "\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x07"
1458 "\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01"
1459 "\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01";
1460 static const BYTE v1CertWithSerial[] = "\x30\x4c\x02\x01\x01\x30\x02\x06\x00"
1461 "\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a"
1462 "\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x07"
1463 "\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01"
1464 "\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01";
1465 static const BYTE bigCert[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
1466 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c"
1467 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
1468 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
1469 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e"
1470 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
1471 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
1472 "\x01";
1473 /* This is the encoded form of the printable string "Juan Lang" */
1474 static const BYTE encodedCommonName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11,
1475 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c,
1476 0x61, 0x6e, 0x67, 0x00 };
1477 static const BYTE serialNum[] = { 0x01 };
1479 static void test_encodeCertToBeSigned(DWORD dwEncoding)
1481 BOOL ret;
1482 BYTE *buf = NULL;
1483 DWORD size = 0;
1484 CERT_INFO info = { 0 };
1486 /* Test with NULL pvStructInfo */
1487 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
1488 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1489 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1490 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1491 /* Test with a V1 cert */
1492 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1493 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1494 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1495 if (buf)
1497 ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
1498 v1Cert[1] + 2, size);
1499 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
1500 LocalFree(buf);
1502 /* Test v2 cert */
1503 info.dwVersion = CERT_V2;
1504 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1505 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1506 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1507 if (buf)
1509 ok(size == v2Cert[1] + 2, "Expected size %d, got %ld\n",
1510 v3Cert[1] + 2, size);
1511 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
1512 LocalFree(buf);
1514 /* Test v3 cert */
1515 info.dwVersion = CERT_V3;
1516 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1517 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1518 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1519 if (buf)
1521 ok(size == v3Cert[1] + 2, "Expected size %d, got %ld\n",
1522 v3Cert[1] + 2, size);
1523 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
1524 LocalFree(buf);
1526 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
1527 * API doesn't prevent it)
1529 info.dwVersion = CERT_V1;
1530 info.cExtension = 1;
1531 info.rgExtension = &criticalExt;
1532 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1533 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1534 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1535 if (buf)
1537 ok(size == v1CertWithConstraints[1] + 2, "Expected size %d, got %ld\n",
1538 v1CertWithConstraints[1] + 2, size);
1539 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
1540 LocalFree(buf);
1542 /* test v1 cert with a serial number */
1543 info.SerialNumber.cbData = sizeof(serialNum);
1544 info.SerialNumber.pbData = (BYTE *)serialNum;
1545 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1546 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1547 if (buf)
1549 ok(size == v1CertWithSerial[1] + 2, "Expected size %d, got %ld\n",
1550 v1CertWithSerial[1] + 2, size);
1551 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
1552 LocalFree(buf);
1554 /* Test v1 cert with an issuer name, a subject name, and a serial number */
1555 info.Issuer.cbData = sizeof(encodedCommonName);
1556 info.Issuer.pbData = (BYTE *)encodedCommonName;
1557 info.Subject.cbData = sizeof(encodedCommonName);
1558 info.Subject.pbData = (BYTE *)encodedCommonName;
1559 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1560 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1561 if (buf)
1563 ok(size == bigCert[1] + 2, "Expected size %d, got %ld\n",
1564 bigCert[1] + 2, size);
1565 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
1566 LocalFree(buf);
1568 /* for now, I let more interesting tests be done for each subcomponent,
1569 * rather than retesting them all here.
1573 static void test_decodeCertToBeSigned(DWORD dwEncoding)
1575 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
1576 v1CertWithConstraints, v1CertWithSerial };
1577 BOOL ret;
1578 BYTE *buf = NULL;
1579 DWORD size = 0, i;
1581 /* Test with NULL pbEncoded */
1582 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
1583 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1584 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1585 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1586 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
1587 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1588 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1589 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1590 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
1591 * minimum a cert must have a non-zero serial number, an issuer, and a
1592 * subject.
1594 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
1596 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
1597 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1598 (BYTE *)&buf, &size);
1599 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1600 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1602 /* Now check with serial number, subject and issuer specified */
1603 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
1604 bigCert[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1605 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1606 if (buf)
1608 CERT_INFO *info = (CERT_INFO *)buf;
1610 ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
1611 sizeof(CERT_INFO), size);
1612 ok(info->SerialNumber.cbData == 1,
1613 "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
1614 ok(*info->SerialNumber.pbData == *serialNum,
1615 "Expected serial number %d, got %d\n", *serialNum,
1616 *info->SerialNumber.pbData);
1617 ok(info->Issuer.cbData == sizeof(encodedCommonName),
1618 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
1619 info->Issuer.cbData);
1620 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
1621 "Unexpected issuer\n");
1622 ok(info->Subject.cbData == sizeof(encodedCommonName),
1623 "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
1624 info->Subject.cbData);
1625 ok(!memcmp(info->Subject.pbData, encodedCommonName,
1626 info->Subject.cbData), "Unexpected subject\n");
1627 LocalFree(buf);
1631 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1632 0xe, 0xf };
1634 static const BYTE signedBigCert[] = {
1635 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
1636 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
1637 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
1638 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1639 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1640 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
1641 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
1642 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
1643 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
1644 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
1645 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
1646 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
1648 static void test_encodeCert(DWORD dwEncoding)
1650 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
1651 * also that bigCert is a NULL-terminated string, so don't count its
1652 * last byte (otherwise the signed cert won't decode.)
1654 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert) - 1, (BYTE *)bigCert },
1655 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
1656 BOOL ret;
1657 BYTE *buf = NULL;
1658 DWORD bufSize = 0;
1660 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
1661 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1662 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1663 if (buf)
1665 ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
1666 sizeof(signedBigCert), bufSize);
1667 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
1668 LocalFree(buf);
1672 static void test_decodeCert(DWORD dwEncoding)
1674 BOOL ret;
1675 BYTE *buf = NULL;
1676 DWORD size = 0;
1678 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
1679 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1680 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1681 if (buf)
1683 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
1685 ok(info->ToBeSigned.cbData == sizeof(bigCert) - 1,
1686 "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert) - 1,
1687 info->ToBeSigned.cbData);
1688 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
1689 "Unexpected cert\n");
1690 ok(info->Signature.cbData == sizeof(hash),
1691 "Expected signature size %d, got %ld\n", sizeof(hash),
1692 info->Signature.cbData);
1693 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
1694 "Unexpected signature\n");
1695 LocalFree(buf);
1699 static void test_registerOIDFunction(void)
1701 static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
1702 BOOL ret;
1704 /* oddly, this succeeds under WinXP; the function name key is merely
1705 * omitted. This may be a side effect of the registry code, I don't know.
1706 * I don't check it because I doubt anyone would depend on it.
1707 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
1708 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1710 /* On windows XP, GetLastError is incorrectly being set with an HRESULT,
1711 * HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)
1713 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
1714 NULL);
1715 ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
1716 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)),
1717 "Expected ERROR_INVALID_PARAMETER: %ld\n", GetLastError());
1718 /* This has no effect, but "succeeds" on XP */
1719 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
1720 "1.2.3.4.5.6.7.8.9.10", NULL, NULL);
1721 ok(ret, "Expected pseudo-success, got %ld\n", GetLastError());
1722 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
1723 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1724 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1725 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
1726 "1.2.3.4.5.6.7.8.9.10");
1727 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
1728 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
1729 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1730 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1731 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
1732 "1.2.3.4.5.6.7.8.9.10");
1733 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
1734 /* This has no effect */
1735 ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
1736 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1737 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1738 /* Check with bogus encoding type: */
1739 ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
1740 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1741 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1742 /* This is written with value 3 verbatim. Thus, the encoding type isn't
1743 * (for now) treated as a mask.
1745 ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
1746 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1747 ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1748 ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
1749 "1.2.3.4.5.6.7.8.9.10");
1750 ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
1753 START_TEST(encode)
1755 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
1756 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
1757 DWORD i;
1759 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
1761 test_encodeInt(encodings[i]);
1762 test_decodeInt(encodings[i]);
1763 test_encodeEnumerated(encodings[i]);
1764 test_decodeEnumerated(encodings[i]);
1765 test_encodeFiletime(encodings[i]);
1766 test_decodeFiletime(encodings[i]);
1767 test_encodeName(encodings[i]);
1768 test_decodeName(encodings[i]);
1769 test_encodeOctets(encodings[i]);
1770 test_decodeOctets(encodings[i]);
1771 test_encodeBits(encodings[i]);
1772 test_decodeBits(encodings[i]);
1773 test_encodeBasicConstraints(encodings[i]);
1774 test_decodeBasicConstraints(encodings[i]);
1775 test_encodeSequenceOfAny(encodings[i]);
1776 test_decodeSequenceOfAny(encodings[i]);
1777 test_encodeExtensions(encodings[i]);
1778 test_decodeExtensions(encodings[i]);
1779 test_encodePublicKeyInfo(encodings[i]);
1780 test_decodePublicKeyInfo(encodings[i]);
1781 test_encodeCertToBeSigned(encodings[i]);
1782 test_decodeCertToBeSigned(encodings[i]);
1783 test_encodeCert(encodings[i]);
1784 test_decodeCert(encodings[i]);
1786 test_registerOIDFunction();