bea24dd26892b625a49b5e885879854908938028
[reactos.git] / reactos / lib / crypt32 / encode.c
1 /*
2 * Copyright 2005 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * This file implements ASN.1 DER encoding and decoding of a limited set of
19 * types. It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
22 *
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
27 *
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
29 *
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
32 */
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 #define NONAMELESSUNION
39
40 #include "windef.h"
41 #include "winbase.h"
42 #include "excpt.h"
43 #include "wincrypt.h"
44 #include "winreg.h"
45 #include "snmp.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
49
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
52
53 /* a few asn.1 tags we need */
54 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
55 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
56 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
57 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
58 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
59 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
60 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
61 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
62 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
63
64 #define ASN_FLAGS_MASK 0xf0
65 #define ASN_TYPE_MASK 0x0f
66
67 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
68
69 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
70 BYTE *, DWORD *);
71 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
72 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
73 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
74 DWORD, DWORD, void *, DWORD *);
75 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
76 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
77
78 /* Prototypes for built-in encoders/decoders. They follow the Ex style
79 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
80 * built-in functions, but the parameters are retained to simplify
81 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
82 * external DLLs that follow these signatures.
83 * FIXME: some built-in functions are suitable to be called directly by
84 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
85 * and memory allocation if requested), others are only suitable to be called
86 * internally. Comment which are which.
87 */
88 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
90 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
91 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
92 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
93 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
96 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
99 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
100 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
101 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
102 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
103 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
105 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
106 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
108 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
109 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
111 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
112 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
113 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
114 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
115 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
117 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
118 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
119 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
120 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
121
122 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
123 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
124 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
125 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
126 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
127 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
128 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
129 * time, doesn't do memory allocation, and doesn't do exception handling.
130 * (This isn't intended to be the externally-called one.)
131 */
132 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
133 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
134 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
135 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
136 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
137 /* Assumes algo->Parameters.pbData is set ahead of time */
138 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
139 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
140 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
141 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
142 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
143 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
144 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
145 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
146 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
147 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
148 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
149 * member has been initialized, doesn't do exception handling, and doesn't do
150 * memory allocation.
151 */
152 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
153 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
154 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
155 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
156 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
157 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
158 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
159 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
160 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
161 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
162 * member has been initialized, doesn't do exception handling, and doesn't do
163 * memory allocation.
164 */
165 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
166 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
167 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
168 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
169 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
170 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
171 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
172 void *pvStructInfo, DWORD *pcbStructInfo);
173
174 /* filter for page-fault exceptions */
175 static WINE_EXCEPTION_FILTER(page_fault)
176 {
177 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
178 return EXCEPTION_EXECUTE_HANDLER;
179 return EXCEPTION_CONTINUE_SEARCH;
180 }
181
182 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
183 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
184 {
185 static HCRYPTOIDFUNCSET set = NULL;
186 BOOL ret = FALSE;
187 HCRYPTOIDFUNCADDR hFunc;
188 CryptEncodeObjectFunc pCryptEncodeObject;
189
190 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
191 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
192 pcbEncoded);
193
194 if (!pbEncoded && !pcbEncoded)
195 {
196 SetLastError(ERROR_INVALID_PARAMETER);
197 return FALSE;
198 }
199
200 /* Try registered DLL first.. */
201 if (!set)
202 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
203 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
204 (void **)&pCryptEncodeObject, &hFunc);
205 if (pCryptEncodeObject)
206 {
207 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
208 pvStructInfo, pbEncoded, pcbEncoded);
209 CryptFreeOIDFunctionAddress(hFunc, 0);
210 }
211 else
212 {
213 /* If not, use CryptEncodeObjectEx */
214 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
215 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
216 }
217 return ret;
218 }
219
220 /* Helper function to check *pcbEncoded, set it to the required size, and
221 * optionally to allocate memory. Assumes pbEncoded is not NULL.
222 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
223 * pointer to the newly allocated memory.
224 */
225 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
226 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
227 DWORD bytesNeeded)
228 {
229 BOOL ret = TRUE;
230
231 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
232 {
233 if (pEncodePara && pEncodePara->pfnAlloc)
234 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
235 else
236 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
237 if (!*(BYTE **)pbEncoded)
238 ret = FALSE;
239 else
240 *pcbEncoded = bytesNeeded;
241 }
242 else if (bytesNeeded > *pcbEncoded)
243 {
244 *pcbEncoded = bytesNeeded;
245 SetLastError(ERROR_MORE_DATA);
246 ret = FALSE;
247 }
248 return ret;
249 }
250
251 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
252 {
253 DWORD bytesNeeded, significantBytes = 0;
254
255 if (len <= 0x7f)
256 bytesNeeded = 1;
257 else
258 {
259 DWORD temp;
260
261 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
262 temp <<= 8, significantBytes--)
263 ;
264 bytesNeeded = significantBytes + 1;
265 }
266 if (!pbEncoded)
267 {
268 *pcbEncoded = bytesNeeded;
269 return TRUE;
270 }
271 if (*pcbEncoded < bytesNeeded)
272 {
273 SetLastError(ERROR_MORE_DATA);
274 return FALSE;
275 }
276 if (len <= 0x7f)
277 *pbEncoded = (BYTE)len;
278 else
279 {
280 DWORD i;
281
282 *pbEncoded++ = significantBytes | 0x80;
283 for (i = 0; i < significantBytes; i++)
284 {
285 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
286 len >>= 8;
287 }
288 }
289 *pcbEncoded = bytesNeeded;
290 return TRUE;
291 }
292
293 struct AsnEncodeSequenceItem
294 {
295 const void *pvStructInfo;
296 CryptEncodeObjectExFunc encodeFunc;
297 DWORD size; /* used during encoding, not for your use */
298 };
299
300 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
301 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
302 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
303 {
304 BOOL ret;
305 DWORD i, dataLen = 0;
306
307 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara,
308 pbEncoded, *pcbEncoded);
309 for (i = 0, ret = TRUE; ret && i < cItem; i++)
310 {
311 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
312 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
313 NULL, &items[i].size);
314 dataLen += items[i].size;
315 }
316 if (ret)
317 {
318 DWORD lenBytes, bytesNeeded;
319
320 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
321 bytesNeeded = 1 + lenBytes + dataLen;
322 if (!pbEncoded)
323 *pcbEncoded = bytesNeeded;
324 else
325 {
326 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
327 pcbEncoded, bytesNeeded)))
328 {
329 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
330 pbEncoded = *(BYTE **)pbEncoded;
331 *pbEncoded++ = ASN_SEQUENCE;
332 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
333 pbEncoded += lenBytes;
334 for (i = 0; ret && i < cItem; i++)
335 {
336 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
337 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
338 NULL, pbEncoded, &items[i].size);
339 pbEncoded += items[i].size;
340 }
341 }
342 }
343 }
344 TRACE("returning %d (%08lx)\n", ret, GetLastError());
345 return ret;
346 }
347
348 struct AsnConstructedItem
349 {
350 BYTE tag;
351 const void *pvStructInfo;
352 CryptEncodeObjectExFunc encodeFunc;
353 };
354
355 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
356 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
357 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
358 {
359 BOOL ret;
360 const struct AsnConstructedItem *item =
361 (const struct AsnConstructedItem *)pvStructInfo;
362 DWORD len;
363
364 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
365 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
366 {
367 DWORD dataLen, bytesNeeded;
368
369 CRYPT_EncodeLen(len, NULL, &dataLen);
370 bytesNeeded = 1 + dataLen + len;
371 if (!pbEncoded)
372 *pcbEncoded = bytesNeeded;
373 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
374 pbEncoded, pcbEncoded, bytesNeeded)))
375 {
376 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
377 pbEncoded = *(BYTE **)pbEncoded;
378 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
379 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
380 pbEncoded += dataLen;
381 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
382 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
383 pbEncoded, &len);
384 }
385 }
386 return ret;
387 }
388
389 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
390 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
391 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
392 {
393 const DWORD *ver = (const DWORD *)pvStructInfo;
394 BOOL ret;
395
396 /* CERT_V1 is not encoded */
397 if (*ver == CERT_V1)
398 {
399 *pcbEncoded = 0;
400 ret = TRUE;
401 }
402 else
403 {
404 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
405
406 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
407 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
408 }
409 return ret;
410 }
411
412 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
413 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
414 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
415 {
416 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
417 BOOL ret;
418
419 if (!pbEncoded)
420 {
421 *pcbEncoded = blob->cbData;
422 ret = TRUE;
423 }
424 else if (*pcbEncoded < blob->cbData)
425 {
426 *pcbEncoded = blob->cbData;
427 SetLastError(ERROR_MORE_DATA);
428 ret = FALSE;
429 }
430 else
431 {
432 if (blob->cbData)
433 memcpy(pbEncoded, blob->pbData, blob->cbData);
434 *pcbEncoded = blob->cbData;
435 ret = TRUE;
436 }
437 return ret;
438 }
439
440 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
443 {
444 BOOL ret;
445 /* This has two filetimes in a row, a NotBefore and a NotAfter */
446 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
447 struct AsnEncodeSequenceItem items[] = {
448 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
449 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
450 };
451
452 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
453 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
454 pcbEncoded);
455 return ret;
456 }
457
458 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
459 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
460 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
461 DWORD *pcbEncoded)
462 {
463 const CRYPT_ALGORITHM_IDENTIFIER *algo =
464 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
465 BOOL ret;
466 struct AsnEncodeSequenceItem items[] = {
467 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
468 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
469 };
470
471 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
472 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
473 pcbEncoded);
474 return ret;
475 }
476
477 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
478 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
479 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
480 {
481 BOOL ret;
482
483 __TRY
484 {
485 const CERT_PUBLIC_KEY_INFO *info =
486 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
487 struct AsnEncodeSequenceItem items[] = {
488 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
489 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
490 };
491
492 TRACE("Encoding public key with OID %s\n",
493 debugstr_a(info->Algorithm.pszObjId));
494 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
495 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
496 pcbEncoded);
497 }
498 __EXCEPT(page_fault)
499 {
500 SetLastError(STATUS_ACCESS_VIOLATION);
501 ret = FALSE;
502 }
503 __ENDTRY
504 return ret;
505 }
506
507 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
510 {
511 BOOL ret;
512
513 __TRY
514 {
515 const CERT_SIGNED_CONTENT_INFO *info =
516 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
517 struct AsnEncodeSequenceItem items[] = {
518 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
519 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
520 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
521 };
522
523 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
524 items[2].encodeFunc = CRYPT_AsnEncodeBits;
525 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
526 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
527 pcbEncoded);
528 }
529 __EXCEPT(page_fault)
530 {
531 SetLastError(STATUS_ACCESS_VIOLATION);
532 ret = FALSE;
533 }
534 __ENDTRY
535 return ret;
536 }
537
538 /* Like in Windows, this blithely ignores the validity of the passed-in
539 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
540 * decode properly, see CRYPT_AsnDecodeCertInfo.
541 */
542 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
543 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
544 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
545 {
546 BOOL ret;
547
548 __TRY
549 {
550 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
551 struct AsnEncodeSequenceItem items[10] = {
552 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
553 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
554 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
555 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
556 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
557 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
558 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
559 { 0 }
560 };
561 struct AsnConstructedItem constructed[3] = { { 0 } };
562 DWORD cItem = 7, cConstructed = 0;
563
564 if (info->IssuerUniqueId.cbData)
565 {
566 constructed[cConstructed].tag = 1;
567 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
568 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
569 items[cItem].pvStructInfo = &constructed[cConstructed];
570 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
571 cConstructed++;
572 cItem++;
573 }
574 if (info->SubjectUniqueId.cbData)
575 {
576 constructed[cConstructed].tag = 2;
577 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
578 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
579 items[cItem].pvStructInfo = &constructed[cConstructed];
580 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
581 cConstructed++;
582 cItem++;
583 }
584 if (info->cExtension)
585 {
586 constructed[cConstructed].tag = 3;
587 constructed[cConstructed].pvStructInfo = &info->cExtension;
588 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
589 items[cItem].pvStructInfo = &constructed[cConstructed];
590 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
591 cConstructed++;
592 cItem++;
593 }
594
595 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
596 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
597 }
598 __EXCEPT(page_fault)
599 {
600 SetLastError(STATUS_ACCESS_VIOLATION);
601 ret = FALSE;
602 }
603 __ENDTRY
604 return ret;
605 }
606
607 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
608 BYTE *pbEncoded, DWORD *pcbEncoded)
609 {
610 struct AsnEncodeSequenceItem items[3] = {
611 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
612 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
613 { 0 }
614 };
615 DWORD cItem = 2;
616 BOOL ret;
617
618 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
619
620 if (entry->cExtension)
621 {
622 items[cItem].pvStructInfo = &entry->cExtension;
623 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
624 cItem++;
625 }
626
627 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
628 pbEncoded, pcbEncoded);
629
630 TRACE("returning %d (%08lx)\n", ret, GetLastError());
631 return ret;
632 }
633
634 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
635 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
636 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
637 {
638 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
639 DWORD bytesNeeded, dataLen, lenBytes, i;
640 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY **)
641 ((const BYTE *)pvStructInfo + sizeof(DWORD));
642 BOOL ret = TRUE;
643
644 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
645 {
646 DWORD size;
647
648 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
649 if (ret)
650 dataLen += size;
651 }
652 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
653 bytesNeeded = 1 + lenBytes + dataLen;
654 if (!pbEncoded)
655 *pcbEncoded = bytesNeeded;
656 else
657 {
658 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
659 pcbEncoded, bytesNeeded)))
660 {
661 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
662 pbEncoded = *(BYTE **)pbEncoded;
663 *pbEncoded++ = ASN_SEQUENCEOF;
664 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
665 pbEncoded += lenBytes;
666 for (i = 0; i < cCRLEntry; i++)
667 {
668 DWORD size = dataLen;
669
670 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
671 pbEncoded += size;
672 dataLen -= size;
673 }
674 }
675 }
676 return ret;
677 }
678
679 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
680 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
681 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
682 {
683 const DWORD *ver = (const DWORD *)pvStructInfo;
684 BOOL ret;
685
686 /* CRL_V1 is not encoded */
687 if (*ver == CRL_V1)
688 {
689 *pcbEncoded = 0;
690 ret = TRUE;
691 }
692 else
693 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
694 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
695 return ret;
696 }
697
698 /* Like in Windows, this blithely ignores the validity of the passed-in
699 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
700 * decode properly, see CRYPT_AsnDecodeCRLInfo.
701 */
702 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
703 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
704 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
705 {
706 BOOL ret;
707
708 __TRY
709 {
710 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
711 struct AsnEncodeSequenceItem items[7] = {
712 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
713 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
714 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
715 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
716 { 0 }
717 };
718 DWORD cItem = 4;
719
720 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
721 {
722 items[cItem].pvStructInfo = &info->NextUpdate;
723 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
724 cItem++;
725 }
726 if (info->cCRLEntry)
727 {
728 items[cItem].pvStructInfo = &info->cCRLEntry;
729 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
730 cItem++;
731 }
732 if (info->cExtension)
733 {
734 items[cItem].pvStructInfo = &info->cExtension;
735 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
736 cItem++;
737 }
738
739 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
740 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
741 }
742 __EXCEPT(page_fault)
743 {
744 SetLastError(STATUS_ACCESS_VIOLATION);
745 ret = FALSE;
746 }
747 __ENDTRY
748 return ret;
749 }
750
751 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
752 DWORD *pcbEncoded)
753 {
754 BOOL ret;
755 struct AsnEncodeSequenceItem items[3] = {
756 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
757 { NULL, NULL, 0 },
758 { NULL, NULL, 0 },
759 };
760 DWORD cItem = 1;
761
762 TRACE("%p, %p, %ld\n", ext, pbEncoded, *pcbEncoded);
763
764 if (ext->fCritical)
765 {
766 items[cItem].pvStructInfo = &ext->fCritical;
767 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
768 cItem++;
769 }
770 items[cItem].pvStructInfo = &ext->Value;
771 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
772 cItem++;
773
774 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
775 pbEncoded, pcbEncoded);
776 TRACE("returning %d (%08lx)\n", ret, GetLastError());
777 return ret;
778 }
779
780 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
781 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
782 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
783 {
784 BOOL ret;
785
786 __TRY
787 {
788 DWORD bytesNeeded, dataLen, lenBytes, i;
789 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
790
791 ret = TRUE;
792 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
793 {
794 DWORD size;
795
796 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
797 if (ret)
798 dataLen += size;
799 }
800 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
801 bytesNeeded = 1 + lenBytes + dataLen;
802 if (!pbEncoded)
803 *pcbEncoded = bytesNeeded;
804 else
805 {
806 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
807 pcbEncoded, bytesNeeded)))
808 {
809 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
810 pbEncoded = *(BYTE **)pbEncoded;
811 *pbEncoded++ = ASN_SEQUENCEOF;
812 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
813 pbEncoded += lenBytes;
814 for (i = 0; i < exts->cExtension; i++)
815 {
816 DWORD size = dataLen;
817
818 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
819 pbEncoded, &size);
820 pbEncoded += size;
821 dataLen -= size;
822 }
823 }
824 }
825 }
826 __EXCEPT(page_fault)
827 {
828 SetLastError(STATUS_ACCESS_VIOLATION);
829 ret = FALSE;
830 }
831 __ENDTRY
832 return ret;
833 }
834
835 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
836 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
837 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
838 {
839 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
840 DWORD bytesNeeded = 0, lenBytes;
841 BOOL ret = TRUE;
842 int firstPos = 0;
843 BYTE firstByte = 0;
844
845 TRACE("%s\n", debugstr_a(pszObjId));
846
847 if (pszObjId)
848 {
849 const char *ptr;
850 int val1, val2;
851
852 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
853 {
854 SetLastError(CRYPT_E_ASN1_ERROR);
855 return FALSE;
856 }
857 bytesNeeded++;
858 firstByte = val1 * 40 + val2;
859 ptr = pszObjId + firstPos;
860 while (ret && *ptr)
861 {
862 int pos;
863
864 /* note I assume each component is at most 32-bits long in base 2 */
865 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
866 {
867 if (val1 >= 0x10000000)
868 bytesNeeded += 5;
869 else if (val1 >= 0x200000)
870 bytesNeeded += 4;
871 else if (val1 >= 0x4000)
872 bytesNeeded += 3;
873 else if (val1 >= 0x80)
874 bytesNeeded += 2;
875 else
876 bytesNeeded += 1;
877 ptr += pos;
878 if (*ptr == '.')
879 ptr++;
880 }
881 else
882 {
883 SetLastError(CRYPT_E_ASN1_ERROR);
884 return FALSE;
885 }
886 }
887 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
888 }
889 else
890 lenBytes = 1;
891 bytesNeeded += 1 + lenBytes;
892 if (pbEncoded)
893 {
894 if (*pcbEncoded < bytesNeeded)
895 {
896 SetLastError(ERROR_MORE_DATA);
897 ret = FALSE;
898 }
899 else
900 {
901 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
902 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
903 pbEncoded += lenBytes;
904 if (pszObjId)
905 {
906 const char *ptr;
907 int val, pos;
908
909 *pbEncoded++ = firstByte;
910 ptr = pszObjId + firstPos;
911 while (ret && *ptr)
912 {
913 sscanf(ptr, "%d%n", &val, &pos);
914 {
915 unsigned char outBytes[5];
916 int numBytes, i;
917
918 if (val >= 0x10000000)
919 numBytes = 5;
920 else if (val >= 0x200000)
921 numBytes = 4;
922 else if (val >= 0x4000)
923 numBytes = 3;
924 else if (val >= 0x80)
925 numBytes = 2;
926 else
927 numBytes = 1;
928 for (i = numBytes; i > 0; i--)
929 {
930 outBytes[i - 1] = val & 0x7f;
931 val >>= 7;
932 }
933 for (i = 0; i < numBytes - 1; i++)
934 *pbEncoded++ = outBytes[i] | 0x80;
935 *pbEncoded++ = outBytes[i];
936 ptr += pos;
937 if (*ptr == '.')
938 ptr++;
939 }
940 }
941 }
942 }
943 }
944 *pcbEncoded = bytesNeeded;
945 return ret;
946 }
947
948 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
949 CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded)
950 {
951 BYTE tag;
952 DWORD bytesNeeded, lenBytes, encodedLen;
953 BOOL ret = TRUE;
954
955 switch (value->dwValueType)
956 {
957 case CERT_RDN_NUMERIC_STRING:
958 tag = ASN_NUMERICSTRING;
959 encodedLen = value->Value.cbData;
960 break;
961 case CERT_RDN_PRINTABLE_STRING:
962 tag = ASN_PRINTABLESTRING;
963 encodedLen = value->Value.cbData;
964 break;
965 case CERT_RDN_IA5_STRING:
966 tag = ASN_IA5STRING;
967 encodedLen = value->Value.cbData;
968 break;
969 case CERT_RDN_ANY_TYPE:
970 /* explicitly disallowed */
971 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
972 return FALSE;
973 default:
974 FIXME("String type %ld unimplemented\n", value->dwValueType);
975 return FALSE;
976 }
977 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
978 bytesNeeded = 1 + lenBytes + encodedLen;
979 if (pbEncoded)
980 {
981 if (*pcbEncoded < bytesNeeded)
982 {
983 SetLastError(ERROR_MORE_DATA);
984 ret = FALSE;
985 }
986 else
987 {
988 *pbEncoded++ = tag;
989 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
990 pbEncoded += lenBytes;
991 switch (value->dwValueType)
992 {
993 case CERT_RDN_NUMERIC_STRING:
994 case CERT_RDN_PRINTABLE_STRING:
995 case CERT_RDN_IA5_STRING:
996 memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
997 }
998 }
999 }
1000 *pcbEncoded = bytesNeeded;
1001 return ret;
1002 }
1003
1004 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1005 CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
1006 {
1007 DWORD bytesNeeded = 0, lenBytes, size;
1008 BOOL ret;
1009
1010 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1011 0, NULL, NULL, &size);
1012 if (ret)
1013 {
1014 bytesNeeded += size;
1015 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1016 * with dwValueType, so "cast" it to get its encoded size
1017 */
1018 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1019 (CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size);
1020 if (ret)
1021 {
1022 bytesNeeded += size;
1023 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1024 bytesNeeded += 1 + lenBytes;
1025 if (pbEncoded)
1026 {
1027 if (*pcbEncoded < bytesNeeded)
1028 {
1029 SetLastError(ERROR_MORE_DATA);
1030 ret = FALSE;
1031 }
1032 else
1033 {
1034 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SEQUENCE;
1035 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1036 &lenBytes);
1037 pbEncoded += lenBytes;
1038 size = bytesNeeded - 1 - lenBytes;
1039 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1040 attr->pszObjId, 0, NULL, pbEncoded, &size);
1041 if (ret)
1042 {
1043 pbEncoded += size;
1044 size = bytesNeeded - 1 - lenBytes - size;
1045 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1046 (CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
1047 &size);
1048 }
1049 }
1050 }
1051 *pcbEncoded = bytesNeeded;
1052 }
1053 }
1054 return ret;
1055 }
1056
1057 static int BLOBComp(const void *l, const void *r)
1058 {
1059 CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
1060 int ret;
1061
1062 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1063 ret = a->cbData - b->cbData;
1064 return ret;
1065 }
1066
1067 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1068 */
1069 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1070 BYTE *pbEncoded, DWORD *pcbEncoded)
1071 {
1072 BOOL ret;
1073 CRYPT_DER_BLOB *blobs = NULL;
1074
1075 __TRY
1076 {
1077 DWORD bytesNeeded = 0, lenBytes, i;
1078
1079 blobs = NULL;
1080 ret = TRUE;
1081 if (rdn->cRDNAttr)
1082 {
1083 blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1084 if (!blobs)
1085 ret = FALSE;
1086 else
1087 memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1088 }
1089 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1090 {
1091 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1092 NULL, &blobs[i].cbData);
1093 if (ret)
1094 bytesNeeded += blobs[i].cbData;
1095 }
1096 if (ret)
1097 {
1098 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1099 bytesNeeded += 1 + lenBytes;
1100 if (pbEncoded)
1101 {
1102 if (*pcbEncoded < bytesNeeded)
1103 {
1104 SetLastError(ERROR_MORE_DATA);
1105 ret = FALSE;
1106 }
1107 else
1108 {
1109 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1110 {
1111 blobs[i].pbData = CryptMemAlloc(blobs[i].cbData);
1112 if (!blobs[i].pbData)
1113 ret = FALSE;
1114 else
1115 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1116 &rdn->rgRDNAttr[i], blobs[i].pbData,
1117 &blobs[i].cbData);
1118 }
1119 if (ret)
1120 {
1121 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
1122 BLOBComp);
1123 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1124 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1125 &lenBytes);
1126 pbEncoded += lenBytes;
1127 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1128 {
1129 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
1130 pbEncoded += blobs[i].cbData;
1131 }
1132 }
1133 }
1134 }
1135 *pcbEncoded = bytesNeeded;
1136 }
1137 if (blobs)
1138 {
1139 for (i = 0; i < rdn->cRDNAttr; i++)
1140 CryptMemFree(blobs[i].pbData);
1141 }
1142 }
1143 __EXCEPT(page_fault)
1144 {
1145 SetLastError(STATUS_ACCESS_VIOLATION);
1146 ret = FALSE;
1147 }
1148 __ENDTRY
1149 CryptMemFree(blobs);
1150 return ret;
1151 }
1152
1153 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1154 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1155 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1156 {
1157 BOOL ret;
1158
1159 __TRY
1160 {
1161 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1162 DWORD bytesNeeded = 0, lenBytes, size, i;
1163
1164 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1165 ret = TRUE;
1166 for (i = 0; ret && i < info->cRDN; i++)
1167 {
1168 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
1169 &size);
1170 if (ret)
1171 bytesNeeded += size;
1172 }
1173 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1174 bytesNeeded += 1 + lenBytes;
1175 if (ret)
1176 {
1177 if (!pbEncoded)
1178 *pcbEncoded = bytesNeeded;
1179 else
1180 {
1181 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1182 pbEncoded, pcbEncoded, bytesNeeded)))
1183 {
1184 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1185 pbEncoded = *(BYTE **)pbEncoded;
1186 *pbEncoded++ = ASN_SEQUENCEOF;
1187 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1188 &lenBytes);
1189 pbEncoded += lenBytes;
1190 for (i = 0; ret && i < info->cRDN; i++)
1191 {
1192 size = bytesNeeded;
1193 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1194 &info->rgRDN[i], pbEncoded, &size);
1195 if (ret)
1196 {
1197 pbEncoded += size;
1198 bytesNeeded -= size;
1199 }
1200 }
1201 }
1202 }
1203 }
1204 }
1205 __EXCEPT(page_fault)
1206 {
1207 SetLastError(STATUS_ACCESS_VIOLATION);
1208 ret = FALSE;
1209 }
1210 __ENDTRY
1211 return ret;
1212 }
1213
1214 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1215 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1216 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1217 {
1218 BOOL val = *(const BOOL *)pvStructInfo, ret;
1219
1220 TRACE("%d\n", val);
1221
1222 if (!pbEncoded)
1223 {
1224 *pcbEncoded = 3;
1225 ret = TRUE;
1226 }
1227 else if (*pcbEncoded < 3)
1228 {
1229 *pcbEncoded = 3;
1230 SetLastError(ERROR_MORE_DATA);
1231 ret = FALSE;
1232 }
1233 else
1234 {
1235 *pcbEncoded = 3;
1236 *pbEncoded++ = ASN_BOOL;
1237 *pbEncoded++ = 1;
1238 *pbEncoded++ = val ? 0xff : 0;
1239 ret = TRUE;
1240 }
1241 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1242 return ret;
1243 }
1244
1245 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1246 BYTE *pbEncoded, DWORD *pcbEncoded)
1247 {
1248 BOOL ret;
1249 DWORD dataLen;
1250
1251 ret = TRUE;
1252 switch (entry->dwAltNameChoice)
1253 {
1254 case CERT_ALT_NAME_RFC822_NAME:
1255 case CERT_ALT_NAME_DNS_NAME:
1256 case CERT_ALT_NAME_URL:
1257 if (entry->u.pwszURL)
1258 {
1259 DWORD i;
1260
1261 /* Not + 1: don't encode the NULL-terminator */
1262 dataLen = lstrlenW(entry->u.pwszURL);
1263 for (i = 0; ret && i < dataLen; i++)
1264 {
1265 if (entry->u.pwszURL[i] > 0x7f)
1266 {
1267 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1268 ret = FALSE;
1269 *pcbEncoded = i;
1270 }
1271 }
1272 }
1273 else
1274 dataLen = 0;
1275 break;
1276 case CERT_ALT_NAME_IP_ADDRESS:
1277 dataLen = entry->u.IPAddress.cbData;
1278 break;
1279 case CERT_ALT_NAME_REGISTERED_ID:
1280 /* FIXME: encode OID */
1281 case CERT_ALT_NAME_OTHER_NAME:
1282 case CERT_ALT_NAME_DIRECTORY_NAME:
1283 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
1284 return FALSE;
1285 default:
1286 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1287 return FALSE;
1288 }
1289 if (ret)
1290 {
1291 DWORD bytesNeeded, lenBytes;
1292
1293 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1294 bytesNeeded = 1 + dataLen + lenBytes;
1295 if (!pbEncoded)
1296 *pcbEncoded = bytesNeeded;
1297 else if (*pcbEncoded < bytesNeeded)
1298 {
1299 SetLastError(ERROR_MORE_DATA);
1300 *pcbEncoded = bytesNeeded;
1301 ret = FALSE;
1302 }
1303 else
1304 {
1305 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1306 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1307 pbEncoded += lenBytes;
1308 switch (entry->dwAltNameChoice)
1309 {
1310 case CERT_ALT_NAME_RFC822_NAME:
1311 case CERT_ALT_NAME_DNS_NAME:
1312 case CERT_ALT_NAME_URL:
1313 {
1314 DWORD i;
1315
1316 for (i = 0; i < dataLen; i++)
1317 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1318 break;
1319 }
1320 case CERT_ALT_NAME_IP_ADDRESS:
1321 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1322 break;
1323 }
1324 if (ret)
1325 *pcbEncoded = bytesNeeded;
1326 }
1327 }
1328 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1329 return ret;
1330 }
1331
1332 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1333 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1334 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1335 {
1336 BOOL ret;
1337
1338 __TRY
1339 {
1340 const CERT_ALT_NAME_INFO *info =
1341 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1342
1343 DWORD bytesNeeded, dataLen, lenBytes, i;
1344
1345 ret = TRUE;
1346 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1347 * can't encode an erroneous entry index if it's bigger than this.
1348 */
1349 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
1350 {
1351 DWORD len;
1352
1353 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
1354 &len);
1355 if (ret)
1356 dataLen += len;
1357 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
1358 {
1359 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1360 * the bad character, now set the index of the bad
1361 * entry
1362 */
1363 *pcbEncoded = (BYTE)i <<
1364 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
1365 }
1366 }
1367 if (ret)
1368 {
1369 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1370 bytesNeeded = 1 + lenBytes + dataLen;
1371 if (!pbEncoded)
1372 {
1373 *pcbEncoded = bytesNeeded;
1374 ret = TRUE;
1375 }
1376 else
1377 {
1378 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1379 pbEncoded, pcbEncoded, bytesNeeded)))
1380 {
1381 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1382 pbEncoded = *(BYTE **)pbEncoded;
1383 *pbEncoded++ = ASN_SEQUENCEOF;
1384 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1385 pbEncoded += lenBytes;
1386 for (i = 0; ret && i < info->cAltEntry; i++)
1387 {
1388 DWORD len = dataLen;
1389
1390 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
1391 pbEncoded, &len);
1392 if (ret)
1393 {
1394 pbEncoded += len;
1395 dataLen -= len;
1396 }
1397 }
1398 }
1399 }
1400 }
1401 }
1402 __EXCEPT(page_fault)
1403 {
1404 SetLastError(STATUS_ACCESS_VIOLATION);
1405 ret = FALSE;
1406 }
1407 __ENDTRY
1408 return ret;
1409 }
1410
1411 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
1412 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1413 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1414 {
1415 BOOL ret;
1416
1417 __TRY
1418 {
1419 const CERT_BASIC_CONSTRAINTS2_INFO *info =
1420 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
1421 struct AsnEncodeSequenceItem items[2] = { { 0 } };
1422 DWORD cItem = 0;
1423
1424 if (info->fCA)
1425 {
1426 items[cItem].pvStructInfo = &info->fCA;
1427 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1428 cItem++;
1429 }
1430 if (info->fPathLenConstraint)
1431 {
1432 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1433 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1434 cItem++;
1435 }
1436 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1437 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1438 }
1439 __EXCEPT(page_fault)
1440 {
1441 SetLastError(STATUS_ACCESS_VIOLATION);
1442 ret = FALSE;
1443 }
1444 __ENDTRY
1445 return ret;
1446 }
1447
1448 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
1449 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1450 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1451 {
1452 BOOL ret;
1453
1454 __TRY
1455 {
1456 const BLOBHEADER *hdr =
1457 (const BLOBHEADER *)pvStructInfo;
1458
1459 if (hdr->bType != PUBLICKEYBLOB)
1460 {
1461 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1462 ret = FALSE;
1463 }
1464 else
1465 {
1466 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
1467 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
1468 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
1469 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
1470 struct AsnEncodeSequenceItem items[] = {
1471 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
1472 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
1473 };
1474
1475 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1476 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1477 pcbEncoded);
1478 }
1479 }
1480 __EXCEPT(page_fault)
1481 {
1482 SetLastError(STATUS_ACCESS_VIOLATION);
1483 ret = FALSE;
1484 }
1485 __ENDTRY
1486 return ret;
1487 }
1488
1489 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
1490 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1491 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1492 {
1493 BOOL ret;
1494
1495 __TRY
1496 {
1497 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
1498 DWORD bytesNeeded, lenBytes;
1499
1500 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
1501 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
1502
1503 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
1504 bytesNeeded = 1 + lenBytes + blob->cbData;
1505 if (!pbEncoded)
1506 {
1507 *pcbEncoded = bytesNeeded;
1508 ret = TRUE;
1509 }
1510 else
1511 {
1512 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1513 pcbEncoded, bytesNeeded)))
1514 {
1515 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1516 pbEncoded = *(BYTE **)pbEncoded;
1517 *pbEncoded++ = ASN_OCTETSTRING;
1518 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
1519 pbEncoded += lenBytes;
1520 if (blob->cbData)
1521 memcpy(pbEncoded, blob->pbData, blob->cbData);
1522 }
1523 }
1524 }
1525 __EXCEPT(page_fault)
1526 {
1527 SetLastError(STATUS_ACCESS_VIOLATION);
1528 ret = FALSE;
1529 }
1530 __ENDTRY
1531 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1532 return ret;
1533 }
1534
1535 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
1536 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1537 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1538 {
1539 BOOL ret;
1540
1541 __TRY
1542 {
1543 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1544 DWORD bytesNeeded, lenBytes, dataBytes;
1545 BYTE unusedBits;
1546
1547 /* yep, MS allows cUnusedBits to be >= 8 */
1548 if (!blob->cUnusedBits)
1549 {
1550 dataBytes = blob->cbData;
1551 unusedBits = 0;
1552 }
1553 else if (blob->cbData * 8 > blob->cUnusedBits)
1554 {
1555 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
1556 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
1557 blob->cUnusedBits;
1558 }
1559 else
1560 {
1561 dataBytes = 0;
1562 unusedBits = 0;
1563 }
1564 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
1565 bytesNeeded = 1 + lenBytes + dataBytes + 1;
1566 if (!pbEncoded)
1567 {
1568 *pcbEncoded = bytesNeeded;
1569 ret = TRUE;
1570 }
1571 else
1572 {
1573 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1574 pcbEncoded, bytesNeeded)))
1575 {
1576 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1577 pbEncoded = *(BYTE **)pbEncoded;
1578 *pbEncoded++ = ASN_BITSTRING;
1579 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
1580 pbEncoded += lenBytes;
1581 *pbEncoded++ = unusedBits;
1582 if (dataBytes)
1583 {
1584 BYTE mask = 0xff << unusedBits;
1585
1586 if (dataBytes > 1)
1587 {
1588 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
1589 pbEncoded += dataBytes - 1;
1590 }
1591 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
1592 }
1593 }
1594 }
1595 }
1596 __EXCEPT(page_fault)
1597 {
1598 SetLastError(STATUS_ACCESS_VIOLATION);
1599 ret = FALSE;
1600 }
1601 __ENDTRY
1602 return ret;
1603 }
1604
1605 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
1606 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1607 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1608 {
1609 BOOL ret;
1610
1611 __TRY
1612 {
1613 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1614 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
1615
1616 ret = TRUE;
1617 if (newBlob.cbData)
1618 {
1619 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
1620 if (newBlob.pbData)
1621 {
1622 DWORD i;
1623
1624 for (i = 0; i < newBlob.cbData; i++)
1625 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
1626 }
1627 else
1628 ret = FALSE;
1629 }
1630 if (ret)
1631 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
1632 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1633 CryptMemFree(newBlob.pbData);
1634 }
1635 __EXCEPT(page_fault)
1636 {
1637 SetLastError(STATUS_ACCESS_VIOLATION);
1638 ret = FALSE;
1639 }
1640 __ENDTRY
1641 return ret;
1642 }
1643
1644 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
1645 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1646 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1647 {
1648 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
1649
1650 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
1651 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1652 }
1653
1654 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
1655 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1656 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1657 {
1658 BOOL ret;
1659
1660 __TRY
1661 {
1662 DWORD significantBytes, lenBytes;
1663 BYTE padByte = 0, bytesNeeded;
1664 BOOL pad = FALSE;
1665 const CRYPT_INTEGER_BLOB *blob =
1666 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1667
1668 significantBytes = blob->cbData;
1669 if (significantBytes)
1670 {
1671 if (blob->pbData[significantBytes - 1] & 0x80)
1672 {
1673 /* negative, lop off leading (little-endian) 0xffs */
1674 for (; significantBytes > 0 &&
1675 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
1676 ;
1677 if (blob->pbData[significantBytes - 1] < 0x80)
1678 {
1679 padByte = 0xff;
1680 pad = TRUE;
1681 }
1682 }
1683 else
1684 {
1685 /* positive, lop off leading (little-endian) zeroes */
1686 for (; significantBytes > 0 &&
1687 !blob->pbData[significantBytes - 1]; significantBytes--)
1688 ;
1689 if (significantBytes == 0)
1690 significantBytes = 1;
1691 if (blob->pbData[significantBytes - 1] > 0x7f)
1692 {
1693 padByte = 0;
1694 pad = TRUE;
1695 }
1696 }
1697 }
1698 if (pad)
1699 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1700 else
1701 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1702 bytesNeeded = 1 + lenBytes + significantBytes;
1703 if (pad)
1704 bytesNeeded++;
1705 if (!pbEncoded)
1706 {
1707 *pcbEncoded = bytesNeeded;
1708 ret = TRUE;
1709 }
1710 else
1711 {
1712 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1713 pcbEncoded, bytesNeeded)))
1714 {
1715 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1716 pbEncoded = *(BYTE **)pbEncoded;
1717 *pbEncoded++ = ASN_INTEGER;
1718 if (pad)
1719 {
1720 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1721 pbEncoded += lenBytes;
1722 *pbEncoded++ = padByte;
1723 }
1724 else
1725 {
1726 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1727 pbEncoded += lenBytes;
1728 }
1729 for (; significantBytes > 0; significantBytes--)
1730 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1731 }
1732 }
1733 }
1734 __EXCEPT(page_fault)
1735 {
1736 SetLastError(STATUS_ACCESS_VIOLATION);
1737 ret = FALSE;
1738 }
1739 __ENDTRY
1740 return ret;
1741 }
1742
1743 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
1744 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1745 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1746 {
1747 BOOL ret;
1748
1749 __TRY
1750 {
1751 DWORD significantBytes, lenBytes;
1752 BYTE bytesNeeded;
1753 BOOL pad = FALSE;
1754 const CRYPT_INTEGER_BLOB *blob =
1755 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1756
1757 significantBytes = blob->cbData;
1758 if (significantBytes)
1759 {
1760 /* positive, lop off leading (little-endian) zeroes */
1761 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
1762 significantBytes--)
1763 ;
1764 if (significantBytes == 0)
1765 significantBytes = 1;
1766 if (blob->pbData[significantBytes - 1] > 0x7f)
1767 pad = TRUE;
1768 }
1769 if (pad)
1770 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1771 else
1772 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1773 bytesNeeded = 1 + lenBytes + significantBytes;
1774 if (pad)
1775 bytesNeeded++;
1776 if (!pbEncoded)
1777 {
1778 *pcbEncoded = bytesNeeded;
1779 ret = TRUE;
1780 }
1781 else
1782 {
1783 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1784 pcbEncoded, bytesNeeded)))
1785 {
1786 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1787 pbEncoded = *(BYTE **)pbEncoded;
1788 *pbEncoded++ = ASN_INTEGER;
1789 if (pad)
1790 {
1791 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1792 pbEncoded += lenBytes;
1793 *pbEncoded++ = 0;
1794 }
1795 else
1796 {
1797 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1798 pbEncoded += lenBytes;
1799 }
1800 for (; significantBytes > 0; significantBytes--)
1801 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1802 }
1803 }
1804 }
1805 __EXCEPT(page_fault)
1806 {
1807 SetLastError(STATUS_ACCESS_VIOLATION);
1808 ret = FALSE;
1809 }
1810 __ENDTRY
1811 return ret;
1812 }
1813
1814 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
1815 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1816 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1817 {
1818 CRYPT_INTEGER_BLOB blob;
1819 BOOL ret;
1820
1821 /* Encode as an unsigned integer, then change the tag to enumerated */
1822 blob.cbData = sizeof(DWORD);
1823 blob.pbData = (BYTE *)pvStructInfo;
1824 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
1825 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1826 if (ret && pbEncoded)
1827 {
1828 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1829 pbEncoded = *(BYTE **)pbEncoded;
1830 pbEncoded[0] = ASN_ENUMERATED;
1831 }
1832 return ret;
1833 }
1834
1835 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
1836 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1837 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1838 {
1839 BOOL ret;
1840
1841 __TRY
1842 {
1843 SYSTEMTIME sysTime;
1844 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1845 * temporary buffer because the output buffer is not NULL-terminated.
1846 */
1847 char buf[16];
1848 static const DWORD bytesNeeded = sizeof(buf) - 1;
1849
1850 if (!pbEncoded)
1851 {
1852 *pcbEncoded = bytesNeeded;
1853 ret = TRUE;
1854 }
1855 else
1856 {
1857 /* Sanity check the year, this is a two-digit year format */
1858 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
1859 &sysTime);
1860 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
1861 {
1862 SetLastError(CRYPT_E_BAD_ENCODE);
1863 ret = FALSE;
1864 }
1865 if (ret)
1866 {
1867 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1868 pbEncoded, pcbEncoded, bytesNeeded)))
1869 {
1870 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1871 pbEncoded = *(BYTE **)pbEncoded;
1872 buf[0] = ASN_UTCTIME;
1873 buf[1] = bytesNeeded - 2;
1874 snprintf(buf + 2, sizeof(buf) - 2,
1875 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
1876 sysTime.wYear - 2000 : sysTime.wYear - 1900,
1877 sysTime.wDay, sysTime.wMonth, sysTime.wHour,
1878 sysTime.wMinute, sysTime.wSecond);
1879 memcpy(pbEncoded, buf, bytesNeeded);
1880 }
1881 }
1882 }
1883 }
1884 __EXCEPT(page_fault)
1885 {
1886 SetLastError(STATUS_ACCESS_VIOLATION);
1887 ret = FALSE;
1888 }
1889 __ENDTRY
1890 return ret;
1891 }
1892
1893 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
1894 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1895 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1896 {
1897 BOOL ret;
1898
1899 __TRY
1900 {
1901 SYSTEMTIME sysTime;
1902 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1903 * temporary buffer because the output buffer is not NULL-terminated.
1904 */
1905 char buf[18];
1906 static const DWORD bytesNeeded = sizeof(buf) - 1;
1907
1908 if (!pbEncoded)
1909 {
1910 *pcbEncoded = bytesNeeded;
1911 ret = TRUE;
1912 }
1913 else
1914 {
1915 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
1916 &sysTime);
1917 if (ret)
1918 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1919 pcbEncoded, bytesNeeded);
1920 if (ret)
1921 {
1922 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1923 pbEncoded = *(BYTE **)pbEncoded;
1924 buf[0] = ASN_GENERALTIME;
1925 buf[1] = bytesNeeded - 2;
1926 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
1927 sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
1928 sysTime.wMinute, sysTime.wSecond);
1929 memcpy(pbEncoded, buf, bytesNeeded);
1930 }
1931 }
1932 }
1933 __EXCEPT(page_fault)
1934 {
1935 SetLastError(STATUS_ACCESS_VIOLATION);
1936 ret = FALSE;
1937 }
1938 __ENDTRY
1939 return ret;
1940 }
1941
1942 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
1943 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1944 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1945 {
1946 BOOL ret;
1947
1948 __TRY
1949 {
1950 SYSTEMTIME sysTime;
1951
1952 /* Check the year, if it's in the UTCTime range call that encode func */
1953 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
1954 return FALSE;
1955 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
1956 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
1957 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1958 else
1959 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
1960 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1961 pcbEncoded);
1962 }
1963 __EXCEPT(page_fault)
1964 {
1965 SetLastError(STATUS_ACCESS_VIOLATION);
1966 ret = FALSE;
1967 }
1968 __ENDTRY
1969 return ret;
1970 }
1971
1972 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
1973 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1974 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1975 {
1976 BOOL ret;
1977
1978 __TRY
1979 {
1980 DWORD bytesNeeded, dataLen, lenBytes, i;
1981 const CRYPT_SEQUENCE_OF_ANY *seq =
1982 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
1983
1984 for (i = 0, dataLen = 0; i < seq->cValue; i++)
1985 dataLen += seq->rgValue[i].cbData;
1986 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1987 bytesNeeded = 1 + lenBytes + dataLen;
1988 if (!pbEncoded)
1989 {
1990 *pcbEncoded = bytesNeeded;
1991 ret = TRUE;
1992 }
1993 else
1994 {
1995 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1996 pcbEncoded, bytesNeeded)))
1997 {
1998 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1999 pbEncoded = *(BYTE **)pbEncoded;
2000 *pbEncoded++ = ASN_SEQUENCEOF;
2001 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2002 pbEncoded += lenBytes;
2003 for (i = 0; i < seq->cValue; i++)
2004 {
2005 memcpy(pbEncoded, seq->rgValue[i].pbData,
2006 seq->rgValue[i].cbData);
2007 pbEncoded += seq->rgValue[i].cbData;
2008 }
2009 }
2010 }
2011 }
2012 __EXCEPT(page_fault)
2013 {
2014 SetLastError(STATUS_ACCESS_VIOLATION);
2015 ret = FALSE;
2016 }
2017 __ENDTRY
2018 return ret;
2019 }
2020
2021 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2022 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
2023 void *pvEncoded, DWORD *pcbEncoded)
2024 {
2025 static HCRYPTOIDFUNCSET set = NULL;
2026 BOOL ret = FALSE;
2027 CryptEncodeObjectExFunc encodeFunc = NULL;
2028 HCRYPTOIDFUNCADDR hFunc = NULL;
2029
2030 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
2031 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
2032 pvEncoded, pcbEncoded);
2033
2034 if (!pvEncoded && !pcbEncoded)
2035 {
2036 SetLastError(ERROR_INVALID_PARAMETER);
2037 return FALSE;
2038 }
2039 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2040 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2041 {
2042 SetLastError(ERROR_FILE_NOT_FOUND);
2043 return FALSE;
2044 }
2045
2046 SetLastError(NOERROR);
2047 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
2048 *(BYTE **)pvEncoded = NULL;
2049 if (!HIWORD(lpszStructType))
2050 {
2051 switch (LOWORD(lpszStructType))
2052 {
2053 case (WORD)X509_CERT:
2054 encodeFunc = CRYPT_AsnEncodeCert;
2055 break;
2056 case (WORD)X509_CERT_TO_BE_SIGNED:
2057 encodeFunc = CRYPT_AsnEncodeCertInfo;
2058 break;
2059 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2060 encodeFunc = CRYPT_AsnEncodeCRLInfo;
2061 break;
2062 case (WORD)X509_EXTENSIONS:
2063 encodeFunc = CRYPT_AsnEncodeExtensions;
2064 break;
2065 case (WORD)X509_NAME:
2066 encodeFunc = CRYPT_AsnEncodeName;
2067 break;
2068 case (WORD)X509_PUBLIC_KEY_INFO:
2069 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
2070 break;
2071 case (WORD)X509_ALTERNATE_NAME:
2072 encodeFunc = CRYPT_AsnEncodeAltName;
2073 break;
2074 case (WORD)X509_BASIC_CONSTRAINTS2:
2075 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2076 break;
2077 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2078 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
2079 break;
2080 case (WORD)X509_OCTET_STRING:
2081 encodeFunc = CRYPT_AsnEncodeOctets;
2082 break;
2083 case (WORD)X509_BITS:
2084 case (WORD)X509_KEY_USAGE:
2085 encodeFunc = CRYPT_AsnEncodeBits;
2086 break;
2087 case (WORD)X509_INTEGER:
2088 encodeFunc = CRYPT_AsnEncodeInt;
2089 break;
2090 case (WORD)X509_MULTI_BYTE_INTEGER:
2091 encodeFunc = CRYPT_AsnEncodeInteger;
2092 break;
2093 case (WORD)X509_MULTI_BYTE_UINT:
2094 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
2095 break;
2096 case (WORD)X509_ENUMERATED:
2097 encodeFunc = CRYPT_AsnEncodeEnumerated;
2098 break;
2099 case (WORD)X509_CHOICE_OF_TIME:
2100 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
2101 break;
2102 case (WORD)X509_SEQUENCE_OF_ANY:
2103 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2104 break;
2105 case (WORD)PKCS_UTC_TIME:
2106 encodeFunc = CRYPT_AsnEncodeUtcTime;
2107 break;
2108 default:
2109 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
2110 }
2111 }
2112 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
2113 encodeFunc = CRYPT_AsnEncodeExtensions;
2114 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
2115 encodeFunc = CRYPT_AsnEncodeUtcTime;
2116 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
2117 encodeFunc = CRYPT_AsnEncodeEnumerated;
2118 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2119 encodeFunc = CRYPT_AsnEncodeBits;
2120 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
2121 encodeFunc = CRYPT_AsnEncodeOctets;
2122 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2123 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2124 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2125 encodeFunc = CRYPT_AsnEncodeAltName;
2126 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2127 encodeFunc = CRYPT_AsnEncodeAltName;
2128 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
2129 encodeFunc = CRYPT_AsnEncodeAltName;
2130 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2131 encodeFunc = CRYPT_AsnEncodeAltName;
2132 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2133 encodeFunc = CRYPT_AsnEncodeAltName;
2134 else
2135 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2136 debugstr_a(lpszStructType));
2137 if (!encodeFunc)
2138 {
2139 if (!set)
2140 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
2141 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2142 (void **)&encodeFunc, &hFunc);
2143 }
2144 if (encodeFunc)
2145 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
2146 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
2147 else
2148 SetLastError(ERROR_FILE_NOT_FOUND);
2149 if (hFunc)
2150 CryptFreeOIDFunctionAddress(hFunc, 0);
2151 return ret;
2152 }
2153
2154 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2155 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2156 DWORD *pcbStructInfo)
2157 {
2158 static HCRYPTOIDFUNCSET set = NULL;
2159 BOOL ret = FALSE;
2160 CryptDecodeObjectFunc pCryptDecodeObject;
2161 HCRYPTOIDFUNCADDR hFunc;
2162
2163 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
2164 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
2165 pvStructInfo, pcbStructInfo);
2166
2167 if (!pvStructInfo && !pcbStructInfo)
2168 {
2169 SetLastError(ERROR_INVALID_PARAMETER);
2170 return FALSE;
2171 }
2172
2173 /* Try registered DLL first.. */
2174 if (!set)
2175 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
2176 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2177 (void **)&pCryptDecodeObject, &hFunc);
2178 if (pCryptDecodeObject)
2179 {
2180 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
2181 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
2182 CryptFreeOIDFunctionAddress(hFunc, 0);
2183 }
2184 else
2185 {
2186 /* If not, use CryptDecodeObjectEx */
2187 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
2188 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
2189 }
2190 return ret;
2191 }
2192
2193 /* Gets the number of length bytes from the given (leading) length byte */
2194 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2195
2196 /* Helper function to get the encoded length of the data starting at pbEncoded,
2197 * where pbEncoded[0] is the tag. If the data are too short to contain a
2198 * length or if the length is too large for cbEncoded, sets an appropriate
2199 * error code and returns FALSE.
2200 */
2201 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
2202 DWORD *len)
2203 {
2204 BOOL ret;
2205
2206 if (cbEncoded <= 1)
2207 {
2208 SetLastError(CRYPT_E_ASN1_CORRUPT);
2209 ret = FALSE;
2210 }
2211 else if (pbEncoded[1] <= 0x7f)
2212 {
2213 if (pbEncoded[1] + 1 > cbEncoded)
2214 {
2215 SetLastError(CRYPT_E_ASN1_EOD);
2216 ret = FALSE;
2217 }
2218 else
2219 {
2220 *len = pbEncoded[1];
2221 ret = TRUE;
2222 }
2223 }
2224 else
2225 {
2226 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
2227
2228 if (lenLen > sizeof(DWORD) + 1)
2229 {
2230 SetLastError(CRYPT_E_ASN1_LARGE);
2231 ret = FALSE;
2232 }
2233 else if (lenLen + 2 > cbEncoded)
2234 {
2235 SetLastError(CRYPT_E_ASN1_CORRUPT);
2236 ret = FALSE;
2237 }
2238 else
2239 {
2240 DWORD out = 0;
2241
2242 pbEncoded += 2;
2243 while (--lenLen)
2244 {
2245 out <<= 8;
2246 out |= *pbEncoded++;
2247 }
2248 if (out + lenLen + 1 > cbEncoded)
2249 {
2250 SetLastError(CRYPT_E_ASN1_EOD);
2251 ret = FALSE;
2252 }
2253 else
2254 {
2255 *len = out;
2256 ret = TRUE;
2257 }
2258 }
2259 }
2260 return ret;
2261 }
2262
2263 /* Helper function to check *pcbStructInfo, set it to the required size, and
2264 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2265 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2266 * pointer to the newly allocated memory.
2267 */
2268 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
2269 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
2270 DWORD bytesNeeded)
2271 {
2272 BOOL ret = TRUE;
2273
2274 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2275 {
2276 if (pDecodePara && pDecodePara->pfnAlloc)
2277 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
2278 else
2279 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
2280 if (!*(BYTE **)pvStructInfo)
2281 ret = FALSE;
2282 else
2283 *pcbStructInfo = bytesNeeded;
2284 }
2285 else if (*pcbStructInfo < bytesNeeded)
2286 {
2287 *pcbStructInfo = bytesNeeded;
2288 SetLastError(ERROR_MORE_DATA);
2289 ret = FALSE;
2290 }
2291 return ret;
2292 }
2293
2294 /* A few of the members need explanation:
2295 * offset:
2296 * A sequence is decoded into a struct. The offset member is the
2297 * offset of this item within that struct.
2298 * decodeFunc:
2299 * The decoder function to use. If this is NULL, then the member isn't
2300 * decoded, but minSize space is reserved for it.
2301 * minSize:
2302 * The minimum amount of space occupied after decoding. You must set this.
2303 * optional:
2304 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2305 * minSize space is filled with 0 for this member. (Any other failure
2306 * results in CRYPT_AsnDecodeSequence failing.)
2307 * hasPointer, pointerOffset, minSize:
2308 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2309 * the offset within the (outer) struct of the data pointer (or to the
2310 * first data pointer, if more than one exist).
2311 * size:
2312 * Used by CRYPT_AsnDecodeSequence, not for your use.
2313 */
2314 struct AsnDecodeSequenceItem
2315 {
2316 DWORD offset;
2317 CryptDecodeObjectExFunc decodeFunc;
2318 DWORD minSize;
2319 BOOL optional;
2320 BOOL hasPointer;
2321 DWORD pointerOffset;
2322 DWORD size;
2323 };
2324
2325 /* This decodes an arbitrary sequence into a contiguous block of memory
2326 * (basically, a struct.) Each element being decoded is described by a struct
2327 * AsnDecodeSequenceItem, see above.
2328 * startingPointer is an optional pointer to the first place where dynamic
2329 * data will be stored. If you know the starting offset, you may pass it
2330 * here. Otherwise, pass NULL, and one will be inferred from the items.
2331 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2332 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2333 */
2334 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
2335 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
2336 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2337 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
2338 {
2339 BOOL ret;
2340
2341 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
2342 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
2343 startingPointer);
2344
2345 if (pbEncoded[0] == ASN_SEQUENCE)
2346 {
2347 DWORD dataLen;
2348
2349 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2350 {
2351 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2352 DWORD i, bytesNeeded = 0, minSize = 0;
2353 const BYTE *ptr;
2354
2355 ptr = pbEncoded + 1 + lenBytes;
2356 for (i = 0; ret && i < cItem; i++)
2357 {
2358 DWORD nextItemLen;
2359
2360 minSize += items[i].minSize;
2361 if (cbEncoded - (ptr - pbEncoded) != 0)
2362 {
2363 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2364 &nextItemLen)))
2365 {
2366 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2367
2368 if (items[i].decodeFunc)
2369 {
2370 TRACE("sizing item %ld\n", i);
2371 ret = items[i].decodeFunc(dwCertEncodingType, NULL,
2372 ptr, 1 + nextItemLenBytes + nextItemLen,
2373 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
2374 &items[i].size);
2375 if (ret)
2376 {
2377 /* Account for alignment padding */
2378 bytesNeeded += items[i].size;
2379 if (items[i].size % sizeof(DWORD))
2380 bytesNeeded += sizeof(DWORD) -
2381 items[i].size % sizeof(DWORD);
2382 ptr += 1 + nextItemLenBytes + nextItemLen;
2383 }
2384 else if (items[i].optional &&
2385 GetLastError() == CRYPT_E_ASN1_BADTAG)
2386 {
2387 TRACE("skipping optional item %ld\n", i);
2388 bytesNeeded += items[i].minSize;
2389 SetLastError(NOERROR);
2390 ret = TRUE;
2391 }
2392 else
2393 TRACE("item %ld failed: %08lx\n", i,
2394 GetLastError());
2395 }
2396 else
2397 bytesNeeded += items[i].minSize;
2398 }
2399 }
2400 else if (items[i].optional)
2401 bytesNeeded += items[i].minSize;
2402 else
2403 {
2404 SetLastError(CRYPT_E_ASN1_CORRUPT);
2405 ret = FALSE;
2406 }
2407 }
2408 if (cbEncoded - (ptr - pbEncoded) != 0)
2409 {
2410 TRACE("%ld remaining bytes, failing\n", cbEncoded -
2411 (ptr - pbEncoded));
2412 SetLastError(CRYPT_E_ASN1_CORRUPT);
2413 ret = FALSE;
2414 }
2415 if (ret)
2416 {
2417 if (!pvStructInfo)
2418 *pcbStructInfo = bytesNeeded;
2419 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2420 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
2421 {
2422 BYTE *nextData;
2423
2424 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2425 pvStructInfo = *(BYTE **)pvStructInfo;
2426 if (startingPointer)
2427 nextData = (BYTE *)startingPointer;
2428 else
2429 nextData = (BYTE *)pvStructInfo + minSize;
2430 memset(pvStructInfo, 0, minSize);
2431 ptr = pbEncoded + 1 + lenBytes;
2432 for (i = 0; ret && i < cItem; i++)
2433 {
2434 if (cbEncoded - (ptr - pbEncoded) != 0)
2435 {
2436 DWORD nextItemLen;
2437 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2438
2439 CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2440 &nextItemLen);
2441 if (items[i].hasPointer)
2442 {
2443 *(BYTE **)((BYTE *)pvStructInfo +
2444 items[i].pointerOffset) = nextData;
2445 }
2446 if (items[i].decodeFunc)
2447 {
2448 TRACE("decoding item %ld\n", i);
2449 ret = items[i].decodeFunc(dwCertEncodingType,
2450 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
2451 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
2452 (BYTE *)pvStructInfo + items[i].offset,
2453 &items[i].size);
2454 if (!ret)
2455 TRACE("item %ld failed: %08lx\n", i,
2456 GetLastError());
2457 }
2458 else
2459 items[i].size = items[i].minSize;
2460 if (ret)
2461 {
2462 if (items[i].hasPointer &&
2463 items[i].size > items[i].minSize)
2464 {
2465 nextData += items[i].size -
2466 items[i].minSize;
2467 /* align nextData to DWORD boundaries */
2468 if (items[i].size % sizeof(DWORD))
2469 {
2470 nextData += sizeof(DWORD) -
2471 items[i].size % sizeof(DWORD);
2472 }
2473 }
2474 ptr += 1 + nextItemLenBytes + nextItemLen;
2475 }
2476 else if (items[i].optional &&
2477 GetLastError() == CRYPT_E_ASN1_BADTAG)
2478 {
2479 SetLastError(NOERROR);
2480 ret = TRUE;
2481 }
2482 }
2483 else if (!items[i].optional)
2484 {
2485 SetLastError(CRYPT_E_ASN1_CORRUPT);
2486 ret = FALSE;
2487 }
2488 }
2489 }
2490 }
2491 }
2492 }
2493 else
2494 {
2495 SetLastError(CRYPT_E_ASN1_BADTAG);
2496 ret = FALSE;
2497 }
2498 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2499 return ret;
2500 }
2501
2502 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2503 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2504 * to CRYPT_E_ASN1_CORRUPT.
2505 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2506 * set!
2507 */
2508 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
2509 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2511 {
2512 BOOL ret;
2513 DWORD dataLen;
2514
2515 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2516 {
2517 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2518 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
2519
2520 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2521 bytesNeeded += 1 + lenBytes + dataLen;
2522
2523 if (!pvStructInfo)
2524 *pcbStructInfo = bytesNeeded;
2525 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2526 pvStructInfo, pcbStructInfo, bytesNeeded)))
2527 {
2528 CRYPT_DER_BLOB *blob = (CRYPT_DER_BLOB *)pvStructInfo;
2529
2530 blob->cbData = 1 + lenBytes + dataLen;
2531 if (blob->cbData)
2532 {
2533 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2534 blob->pbData = (BYTE *)pbEncoded;
2535 else
2536 {
2537 assert(blob->pbData);
2538 memcpy(blob->pbData, pbEncoded, blob->cbData);
2539 }
2540 }
2541 else
2542 {
2543 SetLastError(CRYPT_E_ASN1_CORRUPT);
2544 ret = FALSE;
2545 }
2546 }
2547 }
2548 return ret;
2549 }
2550
2551 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2552 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
2553 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2554 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2555 {
2556 BOOL ret;
2557
2558 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2559 pDecodePara, pvStructInfo, *pcbStructInfo);
2560
2561 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2562 * place.
2563 */
2564 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
2565 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2566 pvStructInfo, pcbStructInfo);
2567 if (ret && pvStructInfo)
2568 {
2569 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2570
2571 if (blob->cbData)
2572 {
2573 DWORD i;
2574 BYTE temp;
2575
2576 for (i = 0; i < blob->cbData / 2; i++)
2577 {
2578 temp = blob->pbData[i];
2579 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2580 blob->pbData[blob->cbData - i - 1] = temp;
2581 }
2582 }
2583 }
2584 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2585 return ret;
2586 }
2587
2588 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
2589 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2590 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2591 {
2592 BOOL ret = TRUE;
2593
2594 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2595 pDecodePara, pvStructInfo, *pcbStructInfo);
2596
2597 __TRY
2598 {
2599 struct AsnDecodeSequenceItem items[] = {
2600 { offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
2601 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2602 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
2603 { offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm),
2604 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2605 FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO,
2606 SignatureAlgorithm.pszObjId), 0 },
2607 { offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
2608 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2609 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
2610 };
2611
2612 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
2613 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
2614 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2615 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2616 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2617 }
2618 __EXCEPT(page_fault)
2619 {
2620 SetLastError(STATUS_ACCESS_VIOLATION);
2621 ret = FALSE;
2622 }
2623 __ENDTRY
2624 return ret;
2625 }
2626
2627 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
2628 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2629 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2630 {
2631 BOOL ret;
2632
2633 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR))
2634 {
2635 DWORD dataLen;
2636
2637 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2638 {
2639 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2640
2641 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2642 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
2643 pvStructInfo, pcbStructInfo);
2644 }
2645 }
2646 else
2647 {
2648 SetLastError(CRYPT_E_ASN1_BADTAG);
2649 ret = FALSE;
2650 }
2651 return ret;
2652 }
2653
2654 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
2655 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2656 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2657 {
2658 BOOL ret;
2659
2660 struct AsnDecodeSequenceItem items[] = {
2661 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
2662 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2663 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
2664 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2665 };
2666
2667 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2668 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2669 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2670 return ret;
2671 }
2672
2673 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
2674 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2675 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2676 {
2677 BOOL ret;
2678
2679 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3))
2680 {
2681 DWORD dataLen;
2682
2683 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2684 {
2685 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2686
2687 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
2688 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
2689 pDecodePara, pvStructInfo, pcbStructInfo);
2690 }
2691 }
2692 else
2693 {
2694 SetLastError(CRYPT_E_ASN1_BADTAG);
2695 ret = FALSE;
2696 }
2697 return ret;
2698 }
2699
2700 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
2701 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2702 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2703 {
2704 BOOL ret = TRUE;
2705
2706 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2707 pDecodePara, pvStructInfo, *pcbStructInfo);
2708
2709 __TRY
2710 {
2711 struct AsnDecodeSequenceItem items[] = {
2712 { offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
2713 sizeof(DWORD), TRUE, FALSE, 0, 0 },
2714 { offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2715 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2716 SerialNumber.pbData), 0 },
2717 { offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
2718 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO,
2719 SignatureAlgorithm.pszObjId), 0 },
2720 { offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
2721 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2722 Issuer.pbData) },
2723 { offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity,
2724 sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 },
2725 { offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
2726 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2727 Subject.pbData) },
2728 { offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo,
2729 sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO,
2730 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
2731 { offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal,
2732 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2733 IssuerUniqueId.pbData), 0 },
2734 { offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal,
2735 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2736 SubjectUniqueId.pbData), 0 },
2737 { offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions,
2738 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO,
2739 rgExtension), 0 },
2740 };
2741
2742 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2743 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2744 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2745 }
2746 __EXCEPT(page_fault)
2747 {
2748 SetLastError(STATUS_ACCESS_VIOLATION);
2749 ret = FALSE;
2750 }
2751 __ENDTRY
2752 return ret;
2753 }
2754
2755 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2756 DWORD dwFlags, PCRL_ENTRY entry, DWORD *pcbEntry)
2757 {
2758 BOOL ret;
2759 struct AsnDecodeSequenceItem items[] = {
2760 { offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2761 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY,
2762 SerialNumber.pbData), 0 },
2763 { offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
2764 sizeof(FILETIME), FALSE, FALSE, 0 },
2765 { offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal,
2766 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY,
2767 rgExtension), 0 },
2768 };
2769
2770 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
2771 *pcbEntry);
2772
2773 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2774 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2775 NULL, entry, pcbEntry, entry ? entry->SerialNumber.pbData : NULL);
2776 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
2777 return ret;
2778 }
2779
2780 typedef struct _WINE_CRL_ENTRIES {
2781 DWORD cCRLEntry;
2782 PCRL_ENTRY rgCRLEntry;
2783 } WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES;
2784
2785 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
2786 * been set prior to calling.
2787 */
2788 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
2789 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2790 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2791 {
2792 BOOL ret;
2793
2794 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2795 pDecodePara, pvStructInfo, *pcbStructInfo);
2796
2797 if (pbEncoded[0] == ASN_SEQUENCEOF)
2798 {
2799 DWORD dataLen, bytesNeeded;
2800
2801 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2802 {
2803 DWORD cCRLEntry = 0;
2804 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2805
2806 bytesNeeded = sizeof(WINE_CRL_ENTRIES);
2807 if (dataLen)
2808 {
2809 const BYTE *ptr;
2810 DWORD size;
2811
2812 for (ptr = pbEncoded + 1 + lenBytes; ret &&
2813 ptr - pbEncoded - 1 - lenBytes < dataLen; )
2814 {
2815 size = 0;
2816 ret = CRYPT_AsnDecodeCRLEntry(ptr,
2817 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
2818 if (ret)
2819 {
2820 DWORD nextLen;
2821
2822 cCRLEntry++;
2823 bytesNeeded += size;
2824 ret = CRYPT_GetLen(ptr,
2825 cbEncoded - (ptr - pbEncoded), &nextLen);
2826 if (ret)
2827 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
2828 }
2829 }
2830 }
2831 if (ret)
2832 {
2833 if (!pvStructInfo)
2834 *pcbStructInfo = bytesNeeded;
2835 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2836 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
2837 {
2838 DWORD size, i;
2839 BYTE *nextData;
2840 const BYTE *ptr;
2841 PWINE_CRL_ENTRIES entries;
2842
2843 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2844 pvStructInfo = *(BYTE **)pvStructInfo;
2845 *pcbStructInfo = bytesNeeded;
2846 entries = (PWINE_CRL_ENTRIES)pvStructInfo;
2847 entries->cCRLEntry = cCRLEntry;
2848 assert(entries->rgCRLEntry);
2849 nextData = (BYTE *)entries->rgCRLEntry +
2850 entries->cCRLEntry * sizeof(CRL_ENTRY);
2851 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
2852 i < cCRLEntry && ptr - pbEncoded - 1 - lenBytes <
2853 dataLen; i++)
2854 {
2855 entries->rgCRLEntry[i].SerialNumber.pbData = nextData;
2856 size = bytesNeeded;
2857 ret = CRYPT_AsnDecodeCRLEntry(ptr,
2858 cbEncoded - (ptr - pbEncoded), dwFlags,
2859 &entries->rgCRLEntry[i], &size);
2860 if (ret)
2861 {
2862 DWORD nextLen;
2863
2864 bytesNeeded -= size;
2865 /* Increment nextData by the difference of the
2866 * minimum size and the actual size.
2867 */
2868 if (size > sizeof(CRL_ENTRY))
2869 nextData += size - sizeof(CRL_ENTRY);
2870 ret = CRYPT_GetLen(ptr,
2871 cbEncoded - (ptr - pbEncoded), &nextLen);
2872 if (ret)
2873 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
2874 }
2875 }
2876 }
2877 }
2878 }
2879 }
2880 else
2881 {
2882 SetLastError(CRYPT_E_ASN1_BADTAG);
2883 ret = FALSE;
2884 }
2885 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
2886 return ret;
2887 }
2888
2889 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
2890 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2891 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2892 {
2893 BOOL ret = TRUE;
2894
2895 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2896 pDecodePara, pvStructInfo, *pcbStructInfo);
2897
2898 __TRY
2899 {
2900 struct AsnDecodeSequenceItem items[] = {
2901 { offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
2902 sizeof(DWORD), TRUE, FALSE, 0, 0 },
2903 { offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
2904 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO,
2905 SignatureAlgorithm.pszObjId), 0 },
2906 { offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
2907 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
2908 Issuer.pbData) },
2909 { offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
2910 sizeof(FILETIME), FALSE, FALSE, 0 },
2911 { offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
2912 sizeof(FILETIME), TRUE, FALSE, 0 },
2913 { offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries,
2914 sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO,
2915 rgCRLEntry), 0 },
2916 /* Note that the extensions are ignored by MS, so I'll ignore them too
2917 */
2918 { offsetof(CRL_INFO, cExtension), NULL,
2919 sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
2920 };
2921
2922 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2923 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2924 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2925 }
2926 __EXCEPT(page_fault)
2927 {
2928 SetLastError(STATUS_ACCESS_VIOLATION);
2929 ret = FALSE;
2930 }
2931 __ENDTRY
2932
2933 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
2934 return ret;
2935 }
2936
2937 /* Differences between this and CRYPT_AsnDecodeOid:
2938 * - pvStructInfo is a LPSTR *, not an LPSTR
2939 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
2940 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
2941 * to
2942 */
2943 static BOOL WINAPI CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType,
2944 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2945 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2946 {
2947 BOOL ret;
2948
2949 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2950 pDecodePara, pvStructInfo, *pcbStructInfo);
2951
2952 ret = CRYPT_AsnDecodeOid(pbEncoded, cbEncoded, dwFlags,
2953 pvStructInfo ? *(LPSTR *)pvStructInfo : NULL, pcbStructInfo);
2954 if (ret || GetLastError() == ERROR_MORE_DATA)
2955 *pcbStructInfo += sizeof(LPSTR);
2956 if (ret && pvStructInfo)
2957 TRACE("returning %s\n", debugstr_a(*(LPSTR *)pvStructInfo));
2958 return ret;
2959 }
2960
2961 /* Warning: assumes ext->pszObjId is set ahead of time! */
2962 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
2963 DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt)
2964 {
2965 struct AsnDecodeSequenceItem items[] = {
2966 { offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper,
2967 sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 },
2968 { offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
2969 sizeof(BOOL), TRUE, FALSE, 0, 0 },
2970 { offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal,
2971 sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION,
2972 Value.pbData) },
2973 };
2974 BOOL ret = TRUE;
2975
2976 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
2977 *pcbExt);
2978
2979 if (ext)
2980 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
2981 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2982 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
2983 ext, pcbExt, ext ? ext->pszObjId : NULL);
2984 if (ext)
2985 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
2986 debugstr_a(ext->pszObjId));
2987 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2988 return ret;
2989 }
2990
2991 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
2992 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2993 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2994 {
2995 BOOL ret = TRUE;
2996
2997 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2998 pDecodePara, pvStructInfo, *pcbStructInfo);
2999
3000 if (pbEncoded[0] == ASN_SEQUENCEOF)
3001 {
3002 DWORD dataLen, bytesNeeded;
3003
3004 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3005 {
3006 DWORD cExtension = 0;
3007 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3008
3009 bytesNeeded = sizeof(CERT_EXTENSIONS);
3010 if (dataLen)
3011 {
3012 const BYTE *ptr;
3013 DWORD size;
3014
3015 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3016 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3017 {
3018 size = 0;
3019 ret = CRYPT_AsnDecodeExtension(ptr,
3020 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3021 if (ret)
3022 {
3023 DWORD nextLen;
3024
3025 cExtension++;
3026 bytesNeeded += size;
3027 ret = CRYPT_GetLen(ptr,
3028 cbEncoded - (ptr - pbEncoded), &nextLen);
3029 if (ret)
3030 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3031 }
3032 }
3033 }
3034 if (ret)
3035 {
3036 if (!pvStructInfo)
3037 *pcbStructInfo = bytesNeeded;
3038 else if (*pcbStructInfo < bytesNeeded)
3039 {
3040 SetLastError(ERROR_MORE_DATA);
3041 *pcbStructInfo = bytesNeeded;
3042 ret = FALSE;
3043 }
3044 else
3045 {
3046 DWORD size, i;
3047 BYTE *nextData;
3048 const BYTE *ptr;
3049 CERT_EXTENSIONS *exts;
3050
3051 *pcbStructInfo = bytesNeeded;
3052 exts = (CERT_EXTENSIONS *)pvStructInfo;
3053 exts->cExtension = cExtension;
3054 assert(exts->rgExtension);
3055 nextData = (BYTE *)exts->rgExtension +
3056 exts->cExtension * sizeof(CERT_EXTENSION);
3057 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3058 i < cExtension && ptr - pbEncoded - 1 - lenBytes <
3059 dataLen; i++)
3060 {
3061 exts->rgExtension[i].pszObjId = (LPSTR)nextData;
3062 size = bytesNeeded;
3063 ret = CRYPT_AsnDecodeExtension(ptr,
3064 cbEncoded - (ptr - pbEncoded), dwFlags,
3065 &exts->rgExtension[i], &size);
3066 if (ret)
3067 {
3068 DWORD nextLen;
3069
3070 bytesNeeded -= size;
3071 if (size > sizeof(CERT_EXTENSION))
3072 nextData += size - sizeof(CERT_EXTENSION);
3073 ret = CRYPT_GetLen(ptr,
3074 cbEncoded - (ptr - pbEncoded), &nextLen);
3075 if (ret)
3076 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3077 }
3078 }
3079 }
3080 }
3081 }
3082 }
3083 else
3084 {
3085 SetLastError(CRYPT_E_ASN1_BADTAG);
3086 ret = FALSE;
3087 }
3088 return ret;
3089 }
3090
3091 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
3092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3093 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3094 {
3095 BOOL ret = TRUE;
3096
3097 __TRY
3098 {
3099 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3100 lpszStructType, pbEncoded, cbEncoded,
3101 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3102 if (ret && pvStructInfo)
3103 {
3104 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3105 pcbStructInfo, *pcbStructInfo);
3106 if (ret)
3107 {
3108 CERT_EXTENSIONS *exts;
3109
3110 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3111 pvStructInfo = *(BYTE **)pvStructInfo;
3112 exts = (CERT_EXTENSIONS *)pvStructInfo;
3113 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
3114 sizeof(CERT_EXTENSIONS));
3115 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3116 lpszStructType, pbEncoded, cbEncoded,
3117 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3118 pcbStructInfo);
3119 }
3120 }
3121 }
3122 __EXCEPT(page_fault)
3123 {
3124 SetLastError(STATUS_ACCESS_VIOLATION);
3125 ret = FALSE;
3126 }
3127 __ENDTRY
3128 return ret;
3129 }
3130
3131 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3132 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
3133 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId)
3134 {
3135 BOOL ret = TRUE;
3136
3137 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, pszObjId,
3138 *pcbObjId);
3139
3140 __TRY
3141 {
3142 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
3143 {
3144 DWORD dataLen;
3145
3146 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3147 {
3148 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3149 DWORD bytesNeeded;
3150
3151 if (dataLen)
3152 {
3153 /* The largest possible string for the first two components
3154 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3155 */
3156 char firstTwo[6];
3157 const BYTE *ptr;
3158
3159 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
3160 pbEncoded[1 + lenBytes] / 40,
3161 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
3162 * 40);
3163 bytesNeeded = strlen(firstTwo) + 1;
3164 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3165 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3166 {
3167 /* large enough for ".4000000" */
3168 char str[9];
3169 int val = 0;
3170
3171 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&