~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/crypt32/tests/encode.c

Version: ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
  3  *
  4  * Copyright 2005 Juan Lang
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 #include <stdio.h>
 21 #include <stdarg.h>
 22 #include <windef.h>
 23 #include <winbase.h>
 24 #include <winerror.h>
 25 #include <wincrypt.h>
 26 
 27 #include "wine/test.h"
 28 
 29 
 30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
 31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
 32 
 33 struct encodedInt
 34 {
 35     int val;
 36     const BYTE *encoded;
 37 };
 38 
 39 static const BYTE bin1[] = {0x02,0x01,0x01};
 40 static const BYTE bin2[] = {0x02,0x01,0x7f};
 41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
 42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
 43 static const BYTE bin5[] = {0x02,0x01,0x80};
 44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
 45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
 46 
 47 static const struct encodedInt ints[] = {
 48  { 1,          bin1 },
 49  { 127,        bin2 },
 50  { 128,        bin3 },
 51  { 256,        bin4 },
 52  { -128,       bin5 },
 53  { -129,       bin6 },
 54  { 0xbaddf00d, bin7 },
 55 };
 56 
 57 struct encodedBigInt
 58 {
 59     const BYTE *val;
 60     const BYTE *encoded;
 61     const BYTE *decoded;
 62 };
 63 
 64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
 65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
 66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
 67 
 68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
 69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
 70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
 71 
 72 static const struct encodedBigInt bigInts[] = {
 73  { bin8, bin9, bin10 },
 74  { bin11, bin12, bin13 },
 75 };
 76 
 77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
 78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
 79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
 80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
 81 
 82 /* Decoded is the same as original, so don't bother storing a separate copy */
 83 static const struct encodedBigInt bigUInts[] = {
 84  { bin14, bin15, NULL },
 85  { bin16, bin17, NULL },
 86 };
 87 
 88 static void test_encodeInt(DWORD dwEncoding)
 89 {
 90     DWORD bufSize = 0;
 91     int i;
 92     BOOL ret;
 93     CRYPT_INTEGER_BLOB blob;
 94     BYTE *buf = NULL;
 95 
 96     /* CryptEncodeObjectEx with NULL bufSize crashes..
 97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
 98      NULL);
 99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     /* check with NULL integer buffer.  Windows XP incorrectly returns an
106      * NTSTATUS.
107      */
108     ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
109      &bufSize);
110     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
111      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
112     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
113     {
114         /* encode as normal integer */
115         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
116          NULL, NULL, &bufSize);
117         ok(ret, "Expected success, got %d\n", GetLastError());
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
119          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
120         ok(ret, "CryptEncodeObjectEx failed: %d\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         /* encode as multibyte integer */
132         blob.cbData = sizeof(ints[i].val);
133         blob.pbData = (BYTE *)&ints[i].val;
134         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
135          0, NULL, NULL, &bufSize);
136         ok(ret, "Expected success, got %d\n", GetLastError());
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
139         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
140         if (buf)
141         {
142             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
143              buf[0]);
144             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
145              buf[1], ints[i].encoded[1]);
146             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
147              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
148             LocalFree(buf);
149         }
150     }
151     /* encode a couple bigger ints, just to show it's little-endian and leading
152      * sign bytes are dropped
153      */
154     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
155     {
156         blob.cbData = strlen((const char*)bigInts[i].val);
157         blob.pbData = (BYTE *)bigInts[i].val;
158         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
159          0, NULL, NULL, &bufSize);
160         ok(ret, "Expected success, got %d\n", GetLastError());
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
163         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
164         if (buf)
165         {
166             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
167              buf[0]);
168             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
169              buf[1], bigInts[i].encoded[1]);
170             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
171              bigInts[i].encoded[1] + 1),
172              "Encoded value didn't match expected\n");
173             LocalFree(buf);
174         }
175     }
176     /* and, encode some uints */
177     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
178     {
179         blob.cbData = strlen((const char*)bigUInts[i].val);
180         blob.pbData = (BYTE*)bigUInts[i].val;
181         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
182          0, NULL, NULL, &bufSize);
183         ok(ret, "Expected success, got %d\n", GetLastError());
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
186         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
187         if (buf)
188         {
189             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
190              buf[0]);
191             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
192              buf[1], bigUInts[i].encoded[1]);
193             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
194              bigUInts[i].encoded[1] + 1),
195              "Encoded value didn't match expected\n");
196             LocalFree(buf);
197         }
198     }
199 }
200 
201 static void test_decodeInt(DWORD dwEncoding)
202 {
203     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
204     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
205     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
206     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
207     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
208     BYTE *buf = NULL;
209     DWORD bufSize = 0;
210     int i;
211     BOOL ret;
212 
213     /* CryptDecodeObjectEx with NULL bufSize crashes..
214     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
215      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
216      */
217     /* check bogus encoding */
218     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
219      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
220     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
221      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
222     /* check with NULL integer buffer */
223     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
224      &bufSize);
225     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
226      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
227     /* check with a valid, but too large, integer */
228     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
229      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
231      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
232     /* check with a DER-encoded string */
233     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
234      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
235     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
236      "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
237     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
238     {
239         /* When the output buffer is NULL, this always succeeds */
240         SetLastError(0xdeadbeef);
241         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
243          &bufSize);
244         ok(ret && GetLastError() == NOERROR,
245          "Expected success and NOERROR, got %d\n", GetLastError());
246         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
247          ints[i].encoded, ints[i].encoded[1] + 2,
248          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
249         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
250         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
251         ok(buf != NULL, "Expected allocated buffer\n");
252         if (buf)
253         {
254             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
255              ints[i].val, *(int *)buf);
256             LocalFree(buf);
257         }
258     }
259     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
260     {
261         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
263          &bufSize);
264         ok(ret && GetLastError() == NOERROR,
265          "Expected success and NOERROR, got %d\n", GetLastError());
266         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
267          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
268          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
269         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
270         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
271         ok(buf != NULL, "Expected allocated buffer\n");
272         if (buf)
273         {
274             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
275 
276             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
277              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
278              blob->cbData);
279             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
280              "Unexpected value\n");
281             LocalFree(buf);
282         }
283     }
284     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
285     {
286         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
288          &bufSize);
289         ok(ret && GetLastError() == NOERROR,
290          "Expected success and NOERROR, got %d\n", GetLastError());
291         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
292          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
293          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
294         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
295         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
296         ok(buf != NULL, "Expected allocated buffer\n");
297         if (buf)
298         {
299             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
300 
301             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
303              blob->cbData);
304             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305              "Unexpected value\n");
306             LocalFree(buf);
307         }
308     }
309     /* Decode the value 1 with long-form length */
310     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
312     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
313     if (buf)
314     {
315         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
316         LocalFree(buf);
317     }
318     /* check with extra bytes at the end */
319     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
320      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
322     if (buf)
323     {
324         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
325         LocalFree(buf);
326     }
327     /* Try to decode some bogus large items */
328     /* The buffer size is smaller than the encoded length, so this should fail
329      * with CRYPT_E_ASN1_EOD if it's being decoded.
330      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
331      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
332      * So this test unfortunately isn't useful.
333     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
334      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
335     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
336      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
337      */
338     /* This will try to decode the buffer and overflow it, check that it's
339      * caught.
340      */
341     if (0)
342     {
343     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
344     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
345      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
346     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
347      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
348     }
349 }
350 
351 static const BYTE bin18[] = {0x0a,0x01,0x01};
352 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
353 
354 /* These are always encoded unsigned, and aren't constrained to be any
355  * particular value
356  */
357 static const struct encodedInt enums[] = {
358  { 1,    bin18 },
359  { -128, bin19 },
360 };
361 
362 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
363  * X509_ENUMERATED.
364  */
365 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
366  szOID_CRL_REASON_CODE };
367 
368 static void test_encodeEnumerated(DWORD dwEncoding)
369 {
370     DWORD i, j;
371 
372     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
373     {
374         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
375         {
376             BOOL ret;
377             BYTE *buf = NULL;
378             DWORD bufSize = 0;
379 
380             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
381              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
382              &bufSize);
383             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
384             if (buf)
385             {
386                 ok(buf[0] == 0xa,
387                  "Got unexpected type %d for enumerated (expected 0xa)\n",
388                  buf[0]);
389                 ok(buf[1] == enums[j].encoded[1],
390                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
391                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
392                  enums[j].encoded[1] + 1),
393                  "Encoded value of 0x%08x didn't match expected\n",
394                  enums[j].val);
395                 LocalFree(buf);
396             }
397         }
398     }
399 }
400 
401 static void test_decodeEnumerated(DWORD dwEncoding)
402 {
403     DWORD i, j;
404 
405     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
406     {
407         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
408         {
409             BOOL ret;
410             DWORD bufSize = sizeof(int);
411             int val;
412 
413             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
414              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
415              (BYTE *)&val, &bufSize);
416             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
417             ok(bufSize == sizeof(int),
418              "Got unexpected size %d for enumerated\n", bufSize);
419             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
420              val, enums[j].val);
421         }
422     }
423 }
424 
425 struct encodedFiletime
426 {
427     SYSTEMTIME sysTime;
428     const BYTE *encodedTime;
429 };
430 
431 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
432  const struct encodedFiletime *time)
433 {
434     FILETIME ft = { 0 };
435     BYTE *buf = NULL;
436     DWORD bufSize = 0;
437     BOOL ret;
438 
439     ret = SystemTimeToFileTime(&time->sysTime, &ft);
440     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
441     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
442      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
443     /* years other than 1950-2050 are not allowed for encodings other than
444      * X509_CHOICE_OF_TIME.
445      */
446     if (structType == X509_CHOICE_OF_TIME ||
447      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
448     {
449         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
450          GetLastError());
451         ok(buf != NULL, "Expected an allocated buffer\n");
452         if (buf)
453         {
454             ok(buf[0] == time->encodedTime[0],
455              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
456              buf[0]);
457             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
458              time->encodedTime[1], bufSize);
459             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
460              "Got unexpected value for time encoding\n");
461             LocalFree(buf);
462         }
463     }
464     else
465         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
466          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
467 }
468 
469 static const char *printSystemTime(const SYSTEMTIME *st)
470 {
471     static char buf[25];
472 
473     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
474      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
475     return buf;
476 }
477 
478 static const char *printFileTime(const FILETIME *ft)
479 {
480     static char buf[25];
481     SYSTEMTIME st;
482 
483     FileTimeToSystemTime(ft, &st);
484     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
485      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
486     return buf;
487 }
488 
489 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
490 {
491     SYSTEMTIME st;
492 
493     FileTimeToSystemTime(got, &st);
494     ok(expected->wYear == st.wYear &&
495      expected->wMonth == st.wMonth &&
496      expected->wDay == st.wDay &&
497      expected->wHour == st.wHour &&
498      expected->wMinute == st.wMinute &&
499      expected->wSecond == st.wSecond &&
500      abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
501      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
502      printSystemTime(expected), printFileTime(got));
503 }
504 
505 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
506  const struct encodedFiletime *time)
507 {
508     FILETIME ft = { 0 };
509     DWORD size = sizeof(ft);
510     BOOL ret;
511 
512     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
513      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
514     /* years other than 1950-2050 are not allowed for encodings other than
515      * X509_CHOICE_OF_TIME.
516      */
517     if (structType == X509_CHOICE_OF_TIME ||
518      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
519     {
520         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
521          GetLastError());
522         compareTime(&time->sysTime, &ft);
523     }
524     else
525         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
526          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
527 }
528 
529 static const BYTE bin20[] = {
530     0x17,0x0d,'','5','','6','','6','1','6','1','','','','Z'};
531 static const BYTE bin21[] = {
532     0x18,0x0f,'1','9','4','5','','6','','6','1','6','1','','','','Z'};
533 static const BYTE bin22[] = {
534     0x18,0x0f,'2','1','4','5','','6','','6','1','6','1','','','','Z'};
535 
536 static const struct encodedFiletime times[] = {
537  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
538  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
539  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
540 };
541 
542 static void test_encodeFiletime(DWORD dwEncoding)
543 {
544     DWORD i;
545 
546     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
547     {
548         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
549         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
550         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
551     }
552 }
553 
554 static const BYTE bin23[] = {
555     0x18,0x13,'1','9','4','5','','6','','6','1','6','1','','','','.','','','','Z'};
556 static const BYTE bin24[] = {
557     0x18,0x13,'1','9','4','5','','6','','6','1','6','1','','','','.','9','9','9','Z'};
558 static const BYTE bin25[] = {
559     0x18,0x13,'1','9','4','5','','6','','6','1','6','1','','','','+','','1','',''};
560 static const BYTE bin26[] = {
561     0x18,0x13,'1','9','4','5','','6','','6','1','6','1','','','','-','','1','',''};
562 static const BYTE bin27[] = {
563     0x18,0x13,'1','9','4','5','','6','','6','1','6','1','','','','-','','1','1','5'};
564 static const BYTE bin28[] = {
565     0x18,0x0a,'2','1','4','5','','6','','6','1','6'};
566 static const BYTE bin29[] = {
567     0x17,0x0a,'4','5','','6','','6','1','6','1',''};
568 static const BYTE bin30[] = {
569     0x17,0x0b,'4','5','','6','','6','1','6','1','','Z'};
570 static const BYTE bin31[] = {
571     0x17,0x0d,'4','5','','6','','6','1','6','1','','+','','1'};
572 static const BYTE bin32[] = {
573     0x17,0x0d,'4','5','','6','','6','1','6','1','','-','','1'};
574 static const BYTE bin33[] = {
575     0x17,0x0f,'4','5','','6','','6','1','6','1','','+','','1','',''};
576 static const BYTE bin34[] = {
577     0x17,0x0f,'4','5','','6','','6','1','6','1','','-','','1','',''};
578 static const BYTE bin35[] = {
579     0x17,0x08, '4','5','','6','','6','1','6'};
580 static const BYTE bin36[] = {
581     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
582 static const BYTE bin37[] = {
583     0x18,0x04, '2','1','4','5'};
584 static const BYTE bin38[] = {
585     0x18,0x08, '2','1','4','5','','6','','6'};
586 
587 static void test_decodeFiletime(DWORD dwEncoding)
588 {
589     static const struct encodedFiletime otherTimes[] = {
590      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
591      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
592      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
593      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
594      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
595      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
596      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
597      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
598      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
599      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
600      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
601      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
602     };
603     /* An oddball case that succeeds in Windows, but doesn't seem correct
604      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
605      */
606     static const unsigned char *bogusTimes[] = {
607      /* oddly, this succeeds on Windows, with year 2765
608      "\x18" "\x0f" "21r50606161000Z",
609       */
610      bin35,
611      bin36,
612      bin37,
613      bin38,
614     };
615     DWORD i, size;
616     FILETIME ft1 = { 0 }, ft2 = { 0 };
617     BOOL ret;
618 
619     /* Check bogus length with non-NULL buffer */
620     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
621     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
622     size = 1;
623     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
624      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
625     ok(!ret && GetLastError() == ERROR_MORE_DATA,
626      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
627     /* Normal tests */
628     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
629     {
630         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
631         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
632         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
633     }
634     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
635     {
636         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
637         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
638         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
639     }
640     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
641     {
642         size = sizeof(ft1);
643         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
644          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
645         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
646          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
647     }
648 }
649 
650 static const char commonName[] = "Juan Lang";
651 static const char surName[] = "Lang";
652 
653 static const BYTE emptySequence[] = { 0x30, 0 };
654 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
655 static const BYTE twoRDNs[] = {
656     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
657     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
658     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
659 static const BYTE encodedTwoRDNs[] = {
660 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
661 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
662 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
663 0x6e,0x67,0x00,
664 };
665 
666 static const BYTE us[] = { 0x55, 0x53 };
667 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
668  0x74, 0x61 };
669 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
670  0x6f, 0x6c, 0x69, 0x73 };
671 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
672  0x76, 0x65, 0x72, 0x73 };
673 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
674  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
675 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
676  0x73, 0x74 };
677 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
678  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
679 
680 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
681 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
682 
683 static CHAR oid_us[]            = "2.5.4.6",
684             oid_minnesota[]     = "2.5.4.8",
685             oid_minneapolis[]   = "2.5.4.7",
686             oid_codeweavers[]   = "2.5.4.10",
687             oid_wine[]          = "2.5.4.11",
688             oid_localhostAttr[] = "2.5.4.3",
689             oid_aric[]          = "1.2.840.113549.1.9.1";
690 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
691                                     { RDNA(minnesota) },
692                                     { RDNA(minneapolis) },
693                                     { RDNA(codeweavers) },
694                                     { RDNA(wine) },
695                                     { RDNA(localhostAttr) },
696                                     { RDNIA5(aric) } };
697 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
698                                            { RDNA(localhostAttr) },
699                                            { RDNA(minnesota) },
700                                            { RDNA(minneapolis) },
701                                            { RDNA(codeweavers) },
702                                            { RDNA(wine) },
703                                            { RDNIA5(aric) } };
704 
705 #undef RDNIA5
706 #undef RDNA
707 
708 static const BYTE encodedRDNAttrs[] = {
709 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
710 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
711 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
712 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
713 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
714 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
715 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
716 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
717 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
718 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
719 };
720 
721 static void test_encodeName(DWORD dwEncoding)
722 {
723     CERT_RDN_ATTR attrs[2];
724     CERT_RDN rdn;
725     CERT_NAME_INFO info;
726     static CHAR oid_common_name[] = szOID_COMMON_NAME,
727                 oid_sur_name[]    = szOID_SUR_NAME;
728     BYTE *buf = NULL;
729     DWORD size = 0;
730     BOOL ret;
731 
732     /* Test with NULL pvStructInfo */
733     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
734      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
735     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
736      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
737     /* Test with empty CERT_NAME_INFO */
738     info.cRDN = 0;
739     info.rgRDN = NULL;
740     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
741      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
742     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
743     if (buf)
744     {
745         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
746          "Got unexpected encoding for empty name\n");
747         LocalFree(buf);
748     }
749     /* Test with bogus CERT_RDN */
750     info.cRDN = 1;
751     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
753     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
754      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
755     /* Test with empty CERT_RDN */
756     rdn.cRDNAttr = 0;
757     rdn.rgRDNAttr = NULL;
758