Fix gcc 4.0 -Wpointer-sign warnings.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29 struct encodedInt
30 {
31     int val;
32     const BYTE *encoded;
33 };
34
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" },
43 };
44
45 struct encodedBigInt
46 {
47     const BYTE *val;
48     const BYTE *encoded;
49     const BYTE *decoded;
50 };
51
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" },
59 };
60
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 },
67 };
68
69 static void test_encodeInt(DWORD dwEncoding)
70 {
71     DWORD bufSize = 0;
72     int i;
73     BOOL ret;
74     CRYPT_INTEGER_BLOB blob;
75     BYTE *buf = NULL;
76
77     /* CryptEncodeObjectEx with NULL bufSize crashes..
78     ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
79      NULL);
80      */
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.
88      */
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++)
94     {
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)
103         {
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);
111         }
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)
122         {
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);
130         }
131     }
132     /* encode a couple bigger ints, just to show it's little-endian and leading
133      * sign bytes are dropped
134      */
135     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
136     {
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)
146         {
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);
155         }
156     }
157     /* and, encode some uints */
158     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
159     {
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)
169         {
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);
178         }
179     }
180 }
181
182 static void test_decodeInt(DWORD dwEncoding)
183 {
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;
193
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);
197      */
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++)
219     {
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)
235         {
236             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
237              ints[i].val, *(int *)buf);
238             LocalFree(buf);
239         }
240     }
241     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
242     {
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)
257         {
258             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
259
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);
266         }
267     }
268     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
269     {
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)
284         {
285             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
286
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);
293         }
294     }
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)
300     {
301         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
302         LocalFree(buf);
303     }
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.
310      */
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.
317      */
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());
322 }
323
324 /* These are always encoded unsigned, and aren't constrained to be any
325  * particular value
326  */
327 static const struct encodedInt enums[] = {
328  { 1,    "\x0a\x01\x01" },
329  { -128, "\x0a\x05\x00\xff\xff\xff\x80" },
330 };
331
332 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
333  * X509_ENUMERATED.
334  */
335 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
336  szOID_CRL_REASON_CODE };
337
338 static void test_encodeEnumerated(DWORD dwEncoding)
339 {
340     DWORD i, j;
341
342     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
343     {
344         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
345         {
346             BOOL ret;
347             BYTE *buf = NULL;
348             DWORD bufSize = 0;
349
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)
355             {
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);
366             }
367         }
368     }
369 }
370
371 static void test_decodeEnumerated(DWORD dwEncoding)
372 {
373     DWORD i, j;
374
375     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
376     {
377         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
378         {
379             BOOL ret;
380             DWORD bufSize = sizeof(int);
381             int val;
382
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);
392         }
393     }
394 }
395
396 struct encodedFiletime
397 {
398     SYSTEMTIME sysTime;
399     const BYTE *encodedTime;
400 };
401
402 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
403  const struct encodedFiletime *time)
404 {
405     FILETIME ft = { 0 };
406     BYTE *buf = NULL;
407     DWORD bufSize = 0;
408     BOOL ret;
409
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.
416      */
417     if (structType == X509_CHOICE_OF_TIME ||
418      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
419     {
420         ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
421          GetLastError());
422         ok(buf != NULL, "Expected an allocated buffer\n");
423         if (buf)
424         {
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);
433         }
434     }
435     else
436         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
437          "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
438 }
439
440 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
441  const struct encodedFiletime *time)
442 {
443     FILETIME ft1 = { 0 }, ft2 = { 0 };
444     DWORD size = sizeof(ft2);
445     BOOL ret;
446
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.
453      */
454     if (structType == X509_CHOICE_OF_TIME ||
455      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
456     {
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");
461     }
462     else
463         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
464          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
465 }
466
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" },
471 };
472
473 static void test_encodeFiletime(DWORD dwEncoding)
474 {
475     DWORD i;
476
477     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
478     {
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]);
482     }
483 }
484
485 static void test_decodeFiletime(DWORD dwEncoding)
486 {
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" },
500     };
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" },
503      */
504     static const char *bogusTimes[] = {
505      /* oddly, this succeeds on Windows, with year 2765
506      "\x18" "\x0f" "21r50606161000Z",
507       */
508      "\x17" "\x08" "45060616",
509      "\x18" "\x0f" "aaaaaaaaaaaaaaZ",
510      "\x18" "\x04" "2145",
511      "\x18" "\x08" "21450606",
512     };
513     DWORD i, size;
514     FILETIME ft1 = { 0 }, ft2 = { 0 };
515     BOOL ret;
516
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++)
527     {
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]);
531     }
532     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
533     {
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]);
537     }
538     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
539     {
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());
545     }
546 }
547
548 struct EncodedName
549 {
550     CERT_RDN_ATTR attr;
551     const BYTE *encoded;
552 };
553
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" },
577  */
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.
581   */
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" },
591 };
592
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";
598
599 static void test_encodeName(DWORD dwEncoding)
600 {
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;
607
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)
620     {
621         ok(!memcmp(buf, emptyName, sizeof(emptyName)),
622          "Got unexpected encoding for empty name\n");
623         LocalFree(buf);
624     }
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)
640     {
641         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
642          "Got unexpected encoding for empty RDN array\n");
643         LocalFree(buf);
644     }
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");
662      */
663     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
664      * the encoded attributes to be swapped.
665      */
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)
680     {
681         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
682          "Got unexpected encoding for two RDN array\n");
683         LocalFree(buf);
684     }
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++)
693     {
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)
700         {
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);
706         }
707     }
708 }
709
710 static void compareNames(const CERT_NAME_INFO *expected,
711  const CERT_NAME_INFO *got)
712 {
713     ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
714      expected->cRDN, got->cRDN);
715     if (expected->cRDN)
716     {
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)
721         {
722             if (expected->rgRDN[0].rgRDNAttr[0].pszObjId &&
723              strlen(expected->rgRDN[0].rgRDNAttr[0].pszObjId))
724             {
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);
734             }
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");
745         }
746     }
747 }
748
749 static void test_decodeName(DWORD dwEncoding)
750 {
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 };
757
758     for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
759     {
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)
774         {
775             compareNames((CERT_NAME_INFO *)buf, &info);
776             LocalFree(buf);
777         }
778     }
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.
788      */
789     if (buf)
790     {
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);
797     }
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)
806     {
807         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
808
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);
813     }
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)
822     {
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 } },
828         };
829
830         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
831         rdn.rgRDNAttr = attrs;
832         compareNames((CERT_NAME_INFO *)buf, &info);
833         LocalFree(buf);
834     }
835 }
836
837 struct encodedOctets
838 {
839     const BYTE *val;
840     const BYTE *encoded;
841 };
842
843 static const struct encodedOctets octets[] = {
844     { "hi", "\x04\x02hi" },
845     { "somelong\xffstring", "\x04\x0fsomelong\xffstring" },
846     { "", "\x04\x00" },
847 };
848
849 static void test_encodeOctets(DWORD dwEncoding)
850 {
851     CRYPT_DATA_BLOB blob;
852     DWORD i;
853
854     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
855     {
856         BYTE *buf = NULL;
857         BOOL ret;
858         DWORD bufSize = 0;
859
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)
866         {
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);
874         }
875     }
876 }
877
878 static void test_decodeOctets(DWORD dwEncoding)
879 {
880     DWORD i;
881
882     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
883     {
884         BYTE *buf = NULL;
885         BOOL ret;
886         DWORD bufSize = 0;
887
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)
897         {
898             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
899
900             if (blob->cbData)
901                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
902                  "Unexpected value\n");
903             LocalFree(buf);
904         }
905     }
906 }
907
908 static const BYTE bytesToEncode[] = { 0xff, 0xff };
909
910 struct encodedBits
911 {
912     DWORD cUnusedBits;
913     const BYTE *encoded;
914     DWORD cbDecoded;
915     const BYTE *decoded;
916 };
917
918 static const struct encodedBits bits[] = {
919     /* normal test case */
920     { 1, "\x03\x03\x01\xff\xfe", 2, "\xff\xfe" },
921     /* strange test case, showing cUnusedBits >= 8 is allowed */
922     { 9, "\x03\x02\x01\xfe", 1, "\xfe" },
923     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
924     { 17, "\x03\x01\x00", 0, NULL },
925 };
926
927 static void test_encodeBits(DWORD dwEncoding)
928 {
929     DWORD i;
930
931     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
932     {
933         CRYPT_BIT_BLOB blob;
934         BOOL ret;
935         BYTE *buf = NULL;
936         DWORD bufSize = 0;
937
938         blob.cbData = sizeof(bytesToEncode);
939         blob.pbData = (BYTE *)bytesToEncode;
940         blob.cUnusedBits = bits[i].cUnusedBits;
941         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
942          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
943         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
944         if (buf)
945         {
946             ok(bufSize == bits[i].encoded[1] + 2,
947              "Got unexpected size %ld, expected %d\n", bufSize,
948              bits[i].encoded[1] + 2);
949             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
950              "Unexpected value\n");
951             LocalFree(buf);
952         }
953     }
954 }
955
956 static void test_decodeBits(DWORD dwEncoding)
957 {
958     static const BYTE ber[] = "\x03\x02\x01\xff";
959     static const BYTE berDecoded = 0xfe;
960     DWORD i;
961     BOOL ret;
962     BYTE *buf = NULL;
963     DWORD bufSize = 0;
964
965     /* normal cases */
966     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
967     {
968         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
969          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
970          &bufSize);
971         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
972         if (buf)
973         {
974             CRYPT_BIT_BLOB *blob;
975
976             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
977              "Got unexpected size %ld, expected >= %ld\n", bufSize,
978              sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
979             blob = (CRYPT_BIT_BLOB *)buf;
980             ok(blob->cbData == bits[i].cbDecoded,
981              "Got unexpected length %ld, expected %ld\n", blob->cbData,
982              bits[i].cbDecoded);
983             if (blob->cbData && bits[i].cbDecoded)
984                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
985                  "Unexpected value\n");
986             LocalFree(buf);
987         }
988     }
989     /* special case: check that something that's valid in BER but not in DER
990      * decodes successfully
991      */
992     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
993      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
994     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
995     if (buf)
996     {
997         CRYPT_BIT_BLOB *blob;
998
999         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1000          "Got unexpected size %ld, expected >= %d\n", bufSize,
1001          sizeof(CRYPT_BIT_BLOB) + berDecoded);
1002         blob = (CRYPT_BIT_BLOB *)buf;
1003         ok(blob->cbData == sizeof(berDecoded),
1004          "Got unexpected length %ld, expected %d\n", blob->cbData,
1005          sizeof(berDecoded));
1006         if (blob->cbData)
1007             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1008         LocalFree(buf);
1009     }
1010 }
1011
1012 struct Constraints2
1013 {
1014     CERT_BASIC_CONSTRAINTS2_INFO info;
1015     const BYTE *encoded;
1016 };
1017
1018 static const struct Constraints2 constraints2[] = {
1019  /* empty constraints */
1020  { { FALSE, FALSE, 0}, "\x30\x00" },
1021  /* can be a CA */
1022  { { TRUE,  FALSE, 0}, "\x30\x03\x01\x01\xff" },
1023  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1024   * but that's not the case
1025   */
1026  { { FALSE, TRUE,  0}, "\x30\x03\x02\x01\x00" },
1027  /* can be a CA and has path length constraints set */
1028  { { TRUE,  TRUE,  1}, "\x30\x06\x01\x01\xff\x02\x01\x01" },
1029 };
1030
1031 static void test_encodeBasicConstraints(DWORD dwEncoding)
1032 {
1033     DWORD i;
1034
1035     /* First test with the simpler info2 */
1036     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1037     {
1038         BOOL ret;
1039         BYTE *buf = NULL;
1040         DWORD bufSize = 0;
1041
1042         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1043          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1044          &bufSize);
1045         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1046         if (buf)
1047         {
1048             ok(bufSize == constraints2[i].encoded[1] + 2,
1049              "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1050              bufSize);
1051             ok(!memcmp(buf, constraints2[i].encoded,
1052              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1053             LocalFree(buf);
1054         }
1055     }
1056 }
1057
1058 static void test_decodeBasicConstraints(DWORD dwEncoding)
1059 {
1060     static const BYTE inverted[] = "\x30\x06\x02\x01\x01\x01\x01\xff";
1061     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 },
1062      "\x30\x06\x01\x01\x01\x02\x01\x01" };
1063     DWORD i;
1064     BOOL ret;
1065     BYTE *buf = NULL;
1066     DWORD bufSize = 0;
1067
1068     /* First test with simpler info2 */
1069     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1070     {
1071         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1072          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1073          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1074         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1075         if (buf)
1076         {
1077             CERT_BASIC_CONSTRAINTS2_INFO *info =
1078              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1079
1080             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1081              "Unexpected value\n");
1082             LocalFree(buf);
1083         }
1084     }
1085     /* Check with the order of encoded elements inverted */
1086     buf = (PBYTE)1;
1087     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1088      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1089      &bufSize);
1090     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1091      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1092     ok(!buf, "Expected buf to be set to NULL\n");
1093     /* Check with a non-DER bool */
1094     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1095      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1096      (BYTE *)&buf, &bufSize);
1097     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1098     if (buf)
1099     {
1100         CERT_BASIC_CONSTRAINTS2_INFO *info =
1101          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1102
1103         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1104         LocalFree(buf);
1105     }
1106     /* Check with a non-basic constraints value */
1107     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1108      names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1109      (BYTE *)&buf, &bufSize);
1110     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1111      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1112 }
1113
1114 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1115  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1116  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1117
1118 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1119  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1120  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1121  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1122
1123 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1124 {
1125     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1126     CRYPT_SEQUENCE_OF_ANY seq;
1127     DWORD i;
1128     BOOL ret;
1129     BYTE *buf = NULL;
1130     DWORD bufSize = 0;
1131
1132     /* Encode a homogenous sequence */
1133     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1134     {
1135         blobs[i].cbData = ints[i].encoded[1] + 2;
1136         blobs[i].pbData = (BYTE *)ints[i].encoded;
1137     }
1138     seq.cValue = sizeof(ints) / sizeof(ints[0]);
1139     seq.rgValue = blobs;
1140
1141     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1142      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1143     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1144     if (buf)
1145     {
1146         ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1147          sizeof(intSequence), bufSize);
1148         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1149         LocalFree(buf);
1150     }
1151     /* Change the type of the first element in the sequence, and give it
1152      * another go
1153      */
1154     blobs[0].cbData = times[0].encodedTime[1] + 2;
1155     blobs[0].pbData = (BYTE *)times[0].encodedTime;
1156     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1157      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1158     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1159     if (buf)
1160     {
1161         ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1162          sizeof(mixedSequence), bufSize);
1163         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1164          "Unexpected value\n");
1165         LocalFree(buf);
1166     }
1167 }
1168
1169 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1170 {
1171     BOOL ret;
1172     BYTE *buf = NULL;
1173     DWORD bufSize = 0;
1174
1175     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1176      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1177     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1178     if (buf)
1179     {
1180         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1181         DWORD i;
1182
1183         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1184          "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1185          seq->cValue);
1186         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1187         {
1188             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1189              "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1190              seq->rgValue[i].cbData);
1191             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1192              ints[i].encoded[1] + 2), "Unexpected value\n");
1193         }
1194         LocalFree(buf);
1195     }
1196     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1197      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1198      &bufSize);
1199     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1200     if (buf)
1201     {
1202         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1203
1204         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1205          "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1206          seq->cValue);
1207         /* Just check the first element since it's all that changed */
1208         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1209          "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1210          seq->rgValue[0].cbData);
1211         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1212          times[0].encodedTime[1] + 2), "Unexpected value\n");
1213         LocalFree(buf);
1214     }
1215 }
1216
1217 struct encodedExtensions
1218 {
1219     CERT_EXTENSIONS exts;
1220     const BYTE *encoded;
1221 };
1222
1223 static CERT_EXTENSION criticalExt =
1224  { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1225 static CERT_EXTENSION nonCriticalExt =
1226  { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1227
1228 static const struct encodedExtensions exts[] = {
1229  { { 0, NULL }, "\x30\x00" },
1230  { { 1, &criticalExt }, "\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff"
1231   "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1232  { { 1, &nonCriticalExt }, "\x30\x11\x30\x0f\x06\x03\x55\x1d\x13"
1233   "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1234 };
1235
1236 #if 0
1237 static void printBytes(const BYTE *pbData, size_t cb)
1238 {
1239     size_t i;
1240
1241     for (i = 0; i < cb; i++)
1242         printf("%02x ", pbData[i]);
1243     putchar('\n');
1244 }
1245 #endif
1246
1247 static void test_encodeExtensions(DWORD dwEncoding)
1248 {
1249     DWORD i;
1250
1251     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1252     {
1253         BOOL ret;
1254         BYTE *buf = NULL;
1255         DWORD bufSize = 0;
1256
1257         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1258          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1259         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1260         if (buf)
1261         {
1262             ok(bufSize == exts[i].encoded[1] + 2,
1263              "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1264             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1265              "Unexpected value\n");
1266             LocalFree(buf);
1267         }
1268     }
1269 }
1270
1271 static void test_decodeExtensions(DWORD dwEncoding)
1272 {
1273     DWORD i;
1274
1275     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1276     {
1277         BOOL ret;
1278         BYTE *buf = NULL;
1279         DWORD bufSize = 0;
1280
1281         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1282          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1283          NULL, (BYTE *)&buf, &bufSize);
1284         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1285         if (buf)
1286         {
1287             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1288             DWORD j;
1289
1290             ok(ext->cExtension == exts[i].exts.cExtension,
1291              "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1292              ext->cExtension);
1293             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1294             {
1295                 ok(!strcmp(ext->rgExtension[j].pszObjId,
1296                  exts[i].exts.rgExtension[j].pszObjId),
1297                  "Expected OID %s, got %s\n",
1298                  exts[i].exts.rgExtension[j].pszObjId,
1299                  ext->rgExtension[j].pszObjId);
1300                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1301                  exts[i].exts.rgExtension[j].Value.pbData,
1302                  exts[i].exts.rgExtension[j].Value.cbData),
1303                  "Unexpected value\n");
1304             }
1305             LocalFree(buf);
1306         }
1307     }
1308 }
1309
1310 static void test_registerOIDFunction(void)
1311 {
1312     static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
1313     BOOL ret;
1314
1315     /* oddly, this succeeds under WinXP; the function name key is merely
1316      * omitted.  This may be a side effect of the registry code, I don't know.
1317      * I don't check it because I doubt anyone would depend on it.
1318     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
1319      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1320      */
1321     /* On windows XP, GetLastError is incorrectly being set with an HRESULT,
1322      * HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)
1323      */
1324     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
1325      NULL);
1326     ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
1327      HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)),
1328      "Expected ERROR_INVALID_PARAMETER: %ld\n", GetLastError());
1329     /* This has no effect, but "succeeds" on XP */
1330     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
1331      "1.2.3.4.5.6.7.8.9.10", NULL, NULL);
1332     ok(ret, "Expected pseudo-success, got %ld\n", GetLastError());
1333     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
1334      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1335     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1336     ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
1337      "1.2.3.4.5.6.7.8.9.10");
1338     ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
1339     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
1340      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1341     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1342     ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
1343      "1.2.3.4.5.6.7.8.9.10");
1344     ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
1345     /* This has no effect */
1346     ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
1347      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1348     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1349     /* Check with bogus encoding type: */
1350     ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
1351      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1352     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1353     /* This is written with value 3 verbatim.  Thus, the encoding type isn't
1354      * (for now) treated as a mask.
1355      */
1356     ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
1357      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
1358     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
1359     ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
1360      "1.2.3.4.5.6.7.8.9.10");
1361     ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
1362 }
1363
1364 START_TEST(encode)
1365 {
1366     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
1367      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
1368     DWORD i;
1369
1370     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
1371     {
1372         test_encodeInt(encodings[i]);
1373         test_decodeInt(encodings[i]);
1374         test_encodeEnumerated(encodings[i]);
1375         test_decodeEnumerated(encodings[i]);
1376         test_encodeFiletime(encodings[i]);
1377         test_decodeFiletime(encodings[i]);
1378         test_encodeName(encodings[i]);
1379         test_decodeName(encodings[i]);
1380         test_encodeOctets(encodings[i]);
1381         test_decodeOctets(encodings[i]);
1382         test_encodeBits(encodings[i]);
1383         test_decodeBits(encodings[i]);
1384         test_encodeBasicConstraints(encodings[i]);
1385         test_decodeBasicConstraints(encodings[i]);
1386         test_encodeSequenceOfAny(encodings[i]);
1387         test_decodeSequenceOfAny(encodings[i]);
1388         test_encodeExtensions(encodings[i]);
1389         test_decodeExtensions(encodings[i]);
1390     }
1391     test_registerOIDFunction();
1392 }