93804319a5008b92ba64172d631d1ccef6dfd390
[reactos.git] / reactos / lib / crypt32 / encode.c
1 /*
2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005 Juan Lang
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * This file implements ASN.1 DER encoding and decoding of a limited set of
20 * types. It isn't a full ASN.1 implementation. Microsoft implements BER
21 * encoding of many of the basic types in msasn1.dll, but that interface is
22 * undocumented, so I implement them here.
23 *
24 * References:
25 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
26 * (available online, look for a PDF copy as the HTML versions tend to have
27 * translation errors.)
28 *
29 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 *
31 * MSDN, especially:
32 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
33 */
34
35 #include "precomp.h"
36
37 static _SEH_FILTER(page_fault)
38 {
39 if (_SEH_GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
40 return _SEH_EXECUTE_HANDLER;
41 return _SEH_CONTINUE_SEARCH;
42 }
43
44 /* This is a bit arbitrary, but to set some limit: */
45 #define MAX_ENCODED_LEN 0x02000000
46
47 /* a few asn.1 tags we need */
48 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
49 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
50 //#define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
51 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
52 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
53 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
54 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
55 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
56 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
57 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
58
59 #define ASN_FLAGS_MASK 0xf0
60 #define ASN_TYPE_MASK 0x0f
61
62 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
63
64 static const WCHAR szDllName[] = { 'D','l','l',0 };
65
66 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
67 BYTE *, DWORD *);
68 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
69 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
70 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
71 DWORD, DWORD, void *, DWORD *);
72 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
73 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
74
75 /* Prototypes for built-in encoders/decoders. They follow the Ex style
76 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
77 * built-in functions, but the parameters are retained to simplify
78 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
79 * external DLLs that follow these signatures.
80 * FIXME: some built-in functions are suitable to be called directly by
81 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
82 * and memory allocation if requested), others are only suitable to be called
83 * internally. Comment which are which.
84 */
85 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
87 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
88 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
90 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
91 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
92 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
93 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
96 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
99 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
100 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
101 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
102 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
103 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
105 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
106 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
108 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
109 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
111 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
112 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
113 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
114 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
115 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
117 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
118
119 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
122 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
123 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
124 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
125 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
126 * time, doesn't do memory allocation, and doesn't do exception handling.
127 * (This isn't intended to be the externally-called one.)
128 */
129 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
130 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
131 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
132 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
133 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
134 /* Assumes algo->Parameters.pbData is set ahead of time */
135 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
136 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
137 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
138 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
139 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
140 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
141 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
142 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
143 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
144 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
145 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
146 * member has been initialized, doesn't do exception handling, and doesn't do
147 * memory allocation.
148 */
149 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
150 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
151 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
152 static BOOL WINAPI CRYPT_AsnDecodeBits(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_AsnDecodeInt(DWORD dwCertEncodingType,
156 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
157 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
158 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
159 * member has been initialized, doesn't do exception handling, and doesn't do
160 * memory allocation.
161 */
162 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
163 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
164 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
165 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
166 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
167 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
168 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
169 void *pvStructInfo, DWORD *pcbStructInfo);
170
171 static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
172 LPCSTR pszOID)
173 {
174 static const char szEncodingTypeFmt[] =
175 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
176 UINT len;
177 char numericOID[7]; /* enough for "#65535" */
178 const char *oid;
179 LPSTR szKey;
180
181 /* MSDN says the encoding type is a mask, but it isn't treated that way.
182 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
183 * "EncodingType 2" would be expected if it were a mask. Instead native
184 * stores values in "EncodingType 3".
185 */
186 if (!HIWORD(pszOID))
187 {
188 snprintf(numericOID, sizeof(numericOID), "#%d", LOWORD(pszOID));
189 oid = numericOID;
190 }
191 else
192 oid = pszOID;
193
194 /* This is enough: the lengths of the two string parameters are explicitly
195 * counted, and we need up to five additional characters for the encoding
196 * type. These are covered by the "%d", "%s", and "%s" characters in the
197 * format specifier that are removed by sprintf.
198 */
199 len = sizeof(szEncodingTypeFmt) + lstrlenA(pszFuncName) + lstrlenA(oid);
200 szKey = CryptMemAlloc(len);
201 if (szKey)
202 sprintf(szKey, szEncodingTypeFmt, dwEncodingType, pszFuncName, oid);
203 return szKey;
204 }
205
206 BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
207 LPCSTR pszOID, LPCWSTR pwszDll, LPCSTR pszOverrideFuncName)
208 {
209 LONG r;
210 HKEY hKey;
211 LPSTR szKey;
212
213 TRACE("%lx %s %s %s %s\n", dwEncodingType, pszFuncName, pszOID,
214 debugstr_w(pwszDll), pszOverrideFuncName);
215
216 /* This only registers functions for encoding certs, not messages */
217 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
218 return TRUE;
219
220 /* Native does nothing pwszDll is NULL */
221 if (!pwszDll)
222 return TRUE;
223
224 /* I'm not matching MS bug for bug here, because I doubt any app depends on
225 * it:
226 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
227 * it creates would never be used
228 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
229 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
230 */
231 if (!pszFuncName || !pszOID)
232 {
233 SetLastError(ERROR_INVALID_PARAMETER);
234 return FALSE;
235 }
236
237 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
238 TRACE("Key name is %s\n", debugstr_a(szKey));
239
240 if (!szKey)
241 return FALSE;
242
243 r = RegCreateKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
244 CryptMemFree(szKey);
245 if(r != ERROR_SUCCESS)
246 return FALSE;
247
248 /* write the values */
249 if (pszOverrideFuncName)
250 RegSetValueExA(hKey, "FuncName", 0, REG_SZ, (const BYTE*)pszOverrideFuncName,
251 lstrlenA(pszOverrideFuncName) + 1);
252 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*) pwszDll,
253 (lstrlenW(pwszDll) + 1) * sizeof (WCHAR));
254
255 RegCloseKey(hKey);
256 return TRUE;
257 }
258
259 BOOL WINAPI CryptUnregisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
260 LPCSTR pszOID)
261 {
262 LPSTR szKey;
263 LONG rc;
264
265 TRACE("%lx %s %s\n", dwEncodingType, pszFuncName, pszOID);
266
267 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
268 return TRUE;
269
270 if (!pszFuncName || !pszOID)
271 {
272 SetLastError(ERROR_INVALID_PARAMETER);
273 return FALSE;
274 }
275
276 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
277 rc = RegDeleteKeyA(HKEY_LOCAL_MACHINE, szKey);
278 CryptMemFree(szKey);
279 if (rc)
280 SetLastError(rc);
281 return rc ? FALSE : TRUE;
282 }
283
284 BOOL WINAPI CryptGetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
285 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD *pdwValueType, BYTE *pbValueData,
286 DWORD *pcbValueData)
287 {
288 LPSTR szKey;
289 LONG rc;
290 HKEY hKey;
291
292 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType, debugstr_a(pszFuncName),
293 debugstr_a(pszOID), debugstr_w(pwszValueName), pdwValueType, pbValueData,
294 pcbValueData);
295
296 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
297 return TRUE;
298
299 if (!pszFuncName || !pszOID || !pwszValueName)
300 {
301 SetLastError(ERROR_INVALID_PARAMETER);
302 return FALSE;
303 }
304
305 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
306 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
307 CryptMemFree(szKey);
308 if (rc)
309 SetLastError(rc);
310 else
311 {
312 rc = RegQueryValueExW(hKey, pwszValueName, NULL, pdwValueType,
313 pbValueData, pcbValueData);
314 if (rc)
315 SetLastError(rc);
316 RegCloseKey(hKey);
317 }
318 return rc ? FALSE : TRUE;
319 }
320
321 BOOL WINAPI CryptSetOIDFunctionValue(DWORD dwEncodingType, LPCSTR pszFuncName,
322 LPCSTR pszOID, LPCWSTR pwszValueName, DWORD dwValueType,
323 const BYTE *pbValueData, DWORD cbValueData)
324 {
325 LPSTR szKey;
326 LONG rc;
327 HKEY hKey;
328
329 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType, debugstr_a(pszFuncName),
330 debugstr_a(pszOID), debugstr_w(pwszValueName), dwValueType, pbValueData,
331 cbValueData);
332
333 if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
334 return TRUE;
335
336 if (!pszFuncName || !pszOID || !pwszValueName)
337 {
338 SetLastError(ERROR_INVALID_PARAMETER);
339 return FALSE;
340 }
341
342 szKey = CRYPT_GetKeyName(dwEncodingType, pszFuncName, pszOID);
343 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
344 CryptMemFree(szKey);
345 if (rc)
346 SetLastError(rc);
347 else
348 {
349 rc = RegSetValueExW(hKey, pwszValueName, 0, dwValueType, pbValueData,
350 cbValueData);
351 if (rc)
352 SetLastError(rc);
353 RegCloseKey(hKey);
354 }
355 return rc ? FALSE : TRUE;
356 }
357
358 /* Gets the registered function named szFuncName for dwCertEncodingType and
359 * lpszStructType, or NULL if one could not be found. *lib will be set to the
360 * handle of the module it's in, or NULL if no module was loaded. If the
361 * return value is NULL, *lib will also be NULL, to simplify error handling.
362 */
363 static void *CRYPT_GetFunc(DWORD dwCertEncodingType, LPCSTR lpszStructType,
364 LPCSTR szFuncName, HMODULE *lib)
365 {
366 void *ret = NULL;
367 char *szKey = CRYPT_GetKeyName(dwCertEncodingType, szFuncName,
368 lpszStructType);
369 const char *funcName;
370 long r;
371 HKEY hKey;
372 DWORD type, size = 0;
373
374 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType, debugstr_a(lpszStructType),
375 debugstr_a(szFuncName), lib);
376
377 *lib = NULL;
378 r = RegOpenKeyA(HKEY_LOCAL_MACHINE, szKey, &hKey);
379 CryptMemFree(szKey);
380 if(r != ERROR_SUCCESS)
381 return NULL;
382
383 RegQueryValueExA(hKey, "FuncName", NULL, &type, NULL, &size);
384 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
385 {
386 funcName = CryptMemAlloc(size);
387 RegQueryValueExA(hKey, "FuncName", NULL, &type, (LPBYTE)funcName,
388 &size);
389 }
390 else
391 funcName = szFuncName;
392 RegQueryValueExW(hKey, szDllName, NULL, &type, NULL, &size);
393 if (GetLastError() == ERROR_MORE_DATA && type == REG_SZ)
394 {
395 LPWSTR dllName = CryptMemAlloc(size);
396
397 RegQueryValueExW(hKey, szDllName, NULL, &type, (LPBYTE)dllName,
398 &size);
399 *lib = LoadLibraryW(dllName);
400 if (*lib)
401 {
402 ret = GetProcAddress(*lib, funcName);
403 if (!ret)
404 {
405 /* Unload the library, the caller doesn't want to unload it
406 * when the return value is NULL.
407 */
408 FreeLibrary(*lib);
409 *lib = NULL;
410 }
411 }
412 CryptMemFree(dllName);
413 }
414 if (funcName != szFuncName)
415 CryptMemFree((char *)funcName);
416 TRACE("returning %p\n", ret);
417 return ret;
418 }
419
420 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
421 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
422 {
423 BOOL ret = FALSE;
424 HMODULE lib;
425 CryptEncodeObjectFunc pCryptEncodeObject;
426
427 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
428 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
429 pcbEncoded);
430
431 if (!pbEncoded && !pcbEncoded)
432 {
433 SetLastError(ERROR_INVALID_PARAMETER);
434 return FALSE;
435 }
436
437 /* Try registered DLL first.. */
438 pCryptEncodeObject =
439 (CryptEncodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
440 lpszStructType, CRYPT_OID_ENCODE_OBJECT_FUNC, &lib);
441 if (pCryptEncodeObject)
442 {
443 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
444 pvStructInfo, pbEncoded, pcbEncoded);
445 FreeLibrary(lib);
446 }
447 else
448 {
449 /* If not, use CryptEncodeObjectEx */
450 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
451 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
452 }
453 return ret;
454 }
455
456 /* Helper function to check *pcbEncoded, set it to the required size, and
457 * optionally to allocate memory. Assumes pbEncoded is not NULL.
458 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
459 * pointer to the newly allocated memory.
460 */
461 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
462 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
463 DWORD bytesNeeded)
464 {
465 BOOL ret = TRUE;
466
467 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
468 {
469 if (pEncodePara && pEncodePara->pfnAlloc)
470 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
471 else
472 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
473 if (!*(BYTE **)pbEncoded)
474 ret = FALSE;
475 else
476 *pcbEncoded = bytesNeeded;
477 }
478 else if (bytesNeeded > *pcbEncoded)
479 {
480 *pcbEncoded = bytesNeeded;
481 SetLastError(ERROR_MORE_DATA);
482 ret = FALSE;
483 }
484 return ret;
485 }
486
487 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
488 {
489 DWORD bytesNeeded, significantBytes = 0;
490
491 if (len <= 0x7f)
492 bytesNeeded = 1;
493 else
494 {
495 DWORD temp;
496
497 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
498 temp <<= 8, significantBytes--)
499 ;
500 bytesNeeded = significantBytes + 1;
501 }
502 if (!pbEncoded)
503 {
504 *pcbEncoded = bytesNeeded;
505 return TRUE;
506 }
507 if (*pcbEncoded < bytesNeeded)
508 {
509 SetLastError(ERROR_MORE_DATA);
510 return FALSE;
511 }
512 if (len <= 0x7f)
513 *pbEncoded = (BYTE)len;
514 else
515 {
516 DWORD i;
517
518 *pbEncoded++ = significantBytes | 0x80;
519 for (i = 0; i < significantBytes; i++)
520 {
521 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
522 len >>= 8;
523 }
524 }
525 *pcbEncoded = bytesNeeded;
526 return TRUE;
527 }
528
529 struct AsnEncodeSequenceItem
530 {
531 const void *pvStructInfo;
532 CryptEncodeObjectExFunc encodeFunc;
533 DWORD size; /* used during encoding, not for your use */
534 };
535
536 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
537 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
538 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
539 {
540 BOOL ret;
541 DWORD i, dataLen = 0;
542
543 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items, cItem, dwFlags, pEncodePara,
544 pbEncoded, *pcbEncoded);
545 for (i = 0, ret = TRUE; ret && i < cItem; i++)
546 {
547 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
548 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
549 NULL, &items[i].size);
550 dataLen += items[i].size;
551 }
552 if (ret)
553 {
554 DWORD lenBytes, bytesNeeded;
555
556 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
557 bytesNeeded = 1 + lenBytes + dataLen;
558 if (!pbEncoded)
559 *pcbEncoded = bytesNeeded;
560 else
561 {
562 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
563 pcbEncoded, bytesNeeded)))
564 {
565 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
566 pbEncoded = *(BYTE **)pbEncoded;
567 *pbEncoded++ = ASN_SEQUENCE;
568 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
569 pbEncoded += lenBytes;
570 for (i = 0; ret && i < cItem; i++)
571 {
572 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
573 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
574 NULL, pbEncoded, &items[i].size);
575 pbEncoded += items[i].size;
576 }
577 }
578 }
579 }
580 TRACE("returning %d (%08lx)\n", ret, GetLastError());
581 return ret;
582 }
583
584 struct AsnConstructedItem
585 {
586 BYTE tag;
587 const void *pvStructInfo;
588 CryptEncodeObjectExFunc encodeFunc;
589 };
590
591 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
592 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
593 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
594 {
595 BOOL ret;
596 const struct AsnConstructedItem *item =
597 (const struct AsnConstructedItem *)pvStructInfo;
598 DWORD len;
599
600 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
601 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
602 {
603 DWORD dataLen, bytesNeeded;
604
605 CRYPT_EncodeLen(len, NULL, &dataLen);
606 bytesNeeded = 1 + dataLen + len;
607 if (!pbEncoded)
608 *pcbEncoded = bytesNeeded;
609 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
610 pbEncoded, pcbEncoded, bytesNeeded)))
611 {
612 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
613 pbEncoded = *(BYTE **)pbEncoded;
614 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
615 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
616 pbEncoded += dataLen;
617 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
618 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
619 pbEncoded, &len);
620 }
621 }
622 return ret;
623 }
624
625 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
626 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
627 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
628 {
629 const DWORD *ver = (const DWORD *)pvStructInfo;
630 BOOL ret;
631
632 /* CERT_V1 is not encoded */
633 if (*ver == CERT_V1)
634 {
635 *pcbEncoded = 0;
636 ret = TRUE;
637 }
638 else
639 {
640 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
641
642 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
643 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
644 }
645 return ret;
646 }
647
648 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
649 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
650 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
651 {
652 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
653 BOOL ret;
654
655 if (!pbEncoded)
656 {
657 *pcbEncoded = blob->cbData;
658 ret = TRUE;
659 }
660 else if (*pcbEncoded < blob->cbData)
661 {
662 *pcbEncoded = blob->cbData;
663 SetLastError(ERROR_MORE_DATA);
664 ret = FALSE;
665 }
666 else
667 {
668 if (blob->cbData)
669 memcpy(pbEncoded, blob->pbData, blob->cbData);
670 *pcbEncoded = blob->cbData;
671 ret = TRUE;
672 }
673 return ret;
674 }
675
676 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
677 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
678 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
679 {
680 BOOL ret;
681 /* This has two filetimes in a row, a NotBefore and a NotAfter */
682 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
683 struct AsnEncodeSequenceItem items[] = {
684 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
685 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
686 };
687
688 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
689 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
690 pcbEncoded);
691 return ret;
692 }
693
694 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
695 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
696 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
697 DWORD *pcbEncoded)
698 {
699 const CRYPT_ALGORITHM_IDENTIFIER *algo =
700 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
701 BOOL ret;
702 struct AsnEncodeSequenceItem items[] = {
703 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
704 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
705 };
706
707 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
708 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
709 pcbEncoded);
710 return ret;
711 }
712
713 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
714 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
715 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
716 {
717 BOOL ret;
718
719 _SEH_TRY
720 {
721 const CERT_PUBLIC_KEY_INFO *info =
722 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
723 struct AsnEncodeSequenceItem items[] = {
724 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
725 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
726 };
727
728 TRACE("Encoding public key with OID %s\n",
729 debugstr_a(info->Algorithm.pszObjId));
730 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
731 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
732 pcbEncoded);
733 }
734 _SEH_EXCEPT(page_fault)
735 {
736 SetLastError(STATUS_ACCESS_VIOLATION);
737 ret = FALSE;
738 }
739 _SEH_END
740 return ret;
741 }
742
743 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
744 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
745 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
746 {
747 BOOL ret;
748
749 _SEH_TRY
750 {
751 const CERT_SIGNED_CONTENT_INFO *info =
752 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
753 struct AsnEncodeSequenceItem items[] = {
754 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
755 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
756 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
757 };
758
759 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
760 items[2].encodeFunc = CRYPT_AsnEncodeBits;
761 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
762 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
763 pcbEncoded);
764 }
765 _SEH_EXCEPT(page_fault)
766 {
767 SetLastError(STATUS_ACCESS_VIOLATION);
768 ret = FALSE;
769 }
770 _SEH_END
771 return ret;
772 }
773
774 /* Like in Windows, this blithely ignores the validity of the passed-in
775 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
776 * decode properly, see CRYPT_AsnDecodeCertInfo.
777 */
778 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
779 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
780 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
781 {
782 BOOL ret;
783
784 _SEH_TRY
785 {
786 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
787 struct AsnEncodeSequenceItem items[10] = {
788 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
789 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
790 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
791 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
792 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
793 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
794 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
795 { 0 }
796 };
797 struct AsnConstructedItem constructed[3] = { { 0 } };
798 DWORD cItem = 7, cConstructed = 0;
799
800 if (info->IssuerUniqueId.cbData)
801 {
802 constructed[cConstructed].tag = 1;
803 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
804 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
805 items[cItem].pvStructInfo = &constructed[cConstructed];
806 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
807 cConstructed++;
808 cItem++;
809 }
810 if (info->SubjectUniqueId.cbData)
811 {
812 constructed[cConstructed].tag = 2;
813 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
814 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
815 items[cItem].pvStructInfo = &constructed[cConstructed];
816 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
817 cConstructed++;
818 cItem++;
819 }
820 if (info->cExtension)
821 {
822 constructed[cConstructed].tag = 3;
823 constructed[cConstructed].pvStructInfo = &info->cExtension;
824 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
825 items[cItem].pvStructInfo = &constructed[cConstructed];
826 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
827 cConstructed++;
828 cItem++;
829 }
830
831 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
832 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
833 }
834 _SEH_EXCEPT(page_fault)
835 {
836 SetLastError(STATUS_ACCESS_VIOLATION);
837 ret = FALSE;
838 }
839 _SEH_END
840 return ret;
841 }
842
843 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
844 BYTE *pbEncoded, DWORD *pcbEncoded)
845 {
846 struct AsnEncodeSequenceItem items[3] = {
847 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
848 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
849 { 0 }
850 };
851 DWORD cItem = 2;
852 BOOL ret;
853
854 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
855
856 if (entry->cExtension)
857 {
858 items[cItem].pvStructInfo = &entry->cExtension;
859 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
860 cItem++;
861 }
862
863 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
864 pbEncoded, pcbEncoded);
865
866 TRACE("returning %d (%08lx)\n", ret, GetLastError());
867 return ret;
868 }
869
870 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
871 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
872 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
873 {
874 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
875 DWORD bytesNeeded, dataLen, lenBytes, i;
876 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY **)
877 ((const BYTE *)pvStructInfo + sizeof(DWORD));
878 BOOL ret = TRUE;
879
880 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
881 {
882 DWORD size;
883
884 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
885 if (ret)
886 dataLen += size;
887 }
888 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
889 bytesNeeded = 1 + lenBytes + dataLen;
890 if (!pbEncoded)
891 *pcbEncoded = bytesNeeded;
892 else
893 {
894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
895 pcbEncoded, bytesNeeded)))
896 {
897 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
898 pbEncoded = *(BYTE **)pbEncoded;
899 *pbEncoded++ = ASN_SEQUENCEOF;
900 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
901 pbEncoded += lenBytes;
902 for (i = 0; i < cCRLEntry; i++)
903 {
904 DWORD size = dataLen;
905
906 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
907 pbEncoded += size;
908 dataLen -= size;
909 }
910 }
911 }
912 return ret;
913 }
914
915 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
916 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
917 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
918 {
919 const DWORD *ver = (const DWORD *)pvStructInfo;
920 BOOL ret;
921
922 /* CRL_V1 is not encoded */
923 if (*ver == CRL_V1)
924 {
925 *pcbEncoded = 0;
926 ret = TRUE;
927 }
928 else
929 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
930 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
931 return ret;
932 }
933
934 /* Like in Windows, this blithely ignores the validity of the passed-in
935 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
936 * decode properly, see CRYPT_AsnDecodeCRLInfo.
937 */
938 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
939 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
940 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
941 {
942 BOOL ret;
943
944 _SEH_TRY
945 {
946 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
947 struct AsnEncodeSequenceItem items[7] = {
948 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
949 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
950 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
951 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
952 { 0 }
953 };
954 DWORD cItem = 4;
955
956 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
957 {
958 items[cItem].pvStructInfo = &info->NextUpdate;
959 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
960 cItem++;
961 }
962 if (info->cCRLEntry)
963 {
964 items[cItem].pvStructInfo = &info->cCRLEntry;
965 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
966 cItem++;
967 }
968 if (info->cExtension)
969 {
970 items[cItem].pvStructInfo = &info->cExtension;
971 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
972 cItem++;
973 }
974
975 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
976 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
977 }
978 _SEH_EXCEPT(page_fault)
979 {
980 SetLastError(STATUS_ACCESS_VIOLATION);
981 ret = FALSE;
982 }
983 _SEH_END
984 return ret;
985 }
986
987 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
988 DWORD *pcbEncoded)
989 {
990 BOOL ret;
991 struct AsnEncodeSequenceItem items[3] = {
992 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
993 { NULL, NULL, 0 },
994 { NULL, NULL, 0 },
995 };
996 DWORD cItem = 1;
997
998 TRACE("%p, %p, %ld\n", ext, pbEncoded, *pcbEncoded);
999
1000 if (ext->fCritical)
1001 {
1002 items[cItem].pvStructInfo = &ext->fCritical;
1003 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1004 cItem++;
1005 }
1006 items[cItem].pvStructInfo = &ext->Value;
1007 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1008 cItem++;
1009
1010 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
1011 pbEncoded, pcbEncoded);
1012 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1013 return ret;
1014 }
1015
1016 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
1017 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1018 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1019 {
1020 BOOL ret;
1021
1022 _SEH_TRY
1023 {
1024 DWORD bytesNeeded, dataLen, lenBytes, i;
1025 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
1026
1027 ret = TRUE;
1028 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
1029 {
1030 DWORD size;
1031
1032 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
1033 if (ret)
1034 dataLen += size;
1035 }
1036 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1037 bytesNeeded = 1 + lenBytes + dataLen;
1038 if (!pbEncoded)
1039 *pcbEncoded = bytesNeeded;
1040 else
1041 {
1042 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1043 pcbEncoded, bytesNeeded)))
1044 {
1045 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1046 pbEncoded = *(BYTE **)pbEncoded;
1047 *pbEncoded++ = ASN_SEQUENCEOF;
1048 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1049 pbEncoded += lenBytes;
1050 for (i = 0; i < exts->cExtension; i++)
1051 {
1052 DWORD size = dataLen;
1053
1054 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
1055 pbEncoded, &size);
1056 pbEncoded += size;
1057 dataLen -= size;
1058 }
1059 }
1060 }
1061 }
1062 _SEH_EXCEPT(page_fault)
1063 {
1064 SetLastError(STATUS_ACCESS_VIOLATION);
1065 ret = FALSE;
1066 }
1067 _SEH_END
1068 return ret;
1069 }
1070
1071 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
1072 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1073 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1074 {
1075 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
1076 DWORD bytesNeeded = 0, lenBytes;
1077 BOOL ret = TRUE;
1078 int firstPos = 0;
1079 BYTE firstByte = 0;
1080
1081 TRACE("%s\n", debugstr_a(pszObjId));
1082
1083 if (pszObjId)
1084 {
1085 const char *ptr;
1086 int val1, val2;
1087
1088 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
1089 {
1090 SetLastError(CRYPT_E_ASN1_ERROR);
1091 return FALSE;
1092 }
1093 bytesNeeded++;
1094 firstByte = val1 * 40 + val2;
1095 ptr = pszObjId + firstPos;
1096 while (ret && *ptr)
1097 {
1098 int pos;
1099
1100 /* note I assume each component is at most 32-bits long in base 2 */
1101 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
1102 {
1103 if (val1 >= 0x10000000)
1104 bytesNeeded += 5;
1105 else if (val1 >= 0x200000)
1106 bytesNeeded += 4;
1107 else if (val1 >= 0x4000)
1108 bytesNeeded += 3;
1109 else if (val1 >= 0x80)
1110 bytesNeeded += 2;
1111 else
1112 bytesNeeded += 1;
1113 ptr += pos;
1114 if (*ptr == '.')
1115 ptr++;
1116 }
1117 else
1118 {
1119 SetLastError(CRYPT_E_ASN1_ERROR);
1120 return FALSE;
1121 }
1122 }
1123 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1124 }
1125 else
1126 lenBytes = 1;
1127 bytesNeeded += 1 + lenBytes;
1128 if (pbEncoded)
1129 {
1130 if (*pcbEncoded < bytesNeeded)
1131 {
1132 SetLastError(ERROR_MORE_DATA);
1133 ret = FALSE;
1134 }
1135 else
1136 {
1137 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
1138 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
1139 pbEncoded += lenBytes;
1140 if (pszObjId)
1141 {
1142 const char *ptr;
1143 int val, pos;
1144
1145 *pbEncoded++ = firstByte;
1146 ptr = pszObjId + firstPos;
1147 while (ret && *ptr)
1148 {
1149 sscanf(ptr, "%d%n", &val, &pos);
1150 {
1151 unsigned char outBytes[5];
1152 int numBytes, i;
1153
1154 if (val >= 0x10000000)
1155 numBytes = 5;
1156 else if (val >= 0x200000)
1157 numBytes = 4;
1158 else if (val >= 0x4000)
1159 numBytes = 3;
1160 else if (val >= 0x80)
1161 numBytes = 2;
1162 else
1163 numBytes = 1;
1164 for (i = numBytes; i > 0; i--)
1165 {
1166 outBytes[i - 1] = val & 0x7f;
1167 val >>= 7;
1168 }
1169 for (i = 0; i < numBytes - 1; i++)
1170 *pbEncoded++ = outBytes[i] | 0x80;
1171 *pbEncoded++ = outBytes[i];
1172 ptr += pos;
1173 if (*ptr == '.')
1174 ptr++;
1175 }
1176 }
1177 }
1178 }
1179 }
1180 *pcbEncoded = bytesNeeded;
1181 return ret;
1182 }
1183
1184 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1185 CERT_NAME_VALUE *value, BYTE *pbEncoded, DWORD *pcbEncoded)
1186 {
1187 BYTE tag;
1188 DWORD bytesNeeded, lenBytes, encodedLen;
1189 BOOL ret = TRUE;
1190
1191 switch (value->dwValueType)
1192 {
1193 case CERT_RDN_NUMERIC_STRING:
1194 tag = ASN_NUMERICSTRING;
1195 encodedLen = value->Value.cbData;
1196 break;
1197 case CERT_RDN_PRINTABLE_STRING:
1198 tag = ASN_PRINTABLESTRING;
1199 encodedLen = value->Value.cbData;
1200 break;
1201 case CERT_RDN_IA5_STRING:
1202 tag = ASN_IA5STRING;
1203 encodedLen = value->Value.cbData;
1204 break;
1205 case CERT_RDN_ANY_TYPE:
1206 /* explicitly disallowed */
1207 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1208 return FALSE;
1209 default:
1210 FIXME("String type %ld unimplemented\n", value->dwValueType);
1211 return FALSE;
1212 }
1213 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1214 bytesNeeded = 1 + lenBytes + encodedLen;
1215 if (pbEncoded)
1216 {
1217 if (*pcbEncoded < bytesNeeded)
1218 {
1219 SetLastError(ERROR_MORE_DATA);
1220 ret = FALSE;
1221 }
1222 else
1223 {
1224 *pbEncoded++ = tag;
1225 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1226 pbEncoded += lenBytes;
1227 switch (value->dwValueType)
1228 {
1229 case CERT_RDN_NUMERIC_STRING:
1230 case CERT_RDN_PRINTABLE_STRING:
1231 case CERT_RDN_IA5_STRING:
1232 memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
1233 }
1234 }
1235 }
1236 *pcbEncoded = bytesNeeded;
1237 return ret;
1238 }
1239
1240 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1241 CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
1242 {
1243 DWORD bytesNeeded = 0, lenBytes, size;
1244 BOOL ret;
1245
1246 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1247 0, NULL, NULL, &size);
1248 if (ret)
1249 {
1250 bytesNeeded += size;
1251 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1252 * with dwValueType, so "cast" it to get its encoded size
1253 */
1254 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1255 (CERT_NAME_VALUE *)&attr->dwValueType, NULL, &size);
1256 if (ret)
1257 {
1258 bytesNeeded += size;
1259 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1260 bytesNeeded += 1 + lenBytes;
1261 if (pbEncoded)
1262 {
1263 if (*pcbEncoded < bytesNeeded)
1264 {
1265 SetLastError(ERROR_MORE_DATA);
1266 ret = FALSE;
1267 }
1268 else
1269 {
1270 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SEQUENCE;
1271 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1272 &lenBytes);
1273 pbEncoded += lenBytes;
1274 size = bytesNeeded - 1 - lenBytes;
1275 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1276 attr->pszObjId, 0, NULL, pbEncoded, &size);
1277 if (ret)
1278 {
1279 pbEncoded += size;
1280 size = bytesNeeded - 1 - lenBytes - size;
1281 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1282 (CERT_NAME_VALUE *)&attr->dwValueType, pbEncoded,
1283 &size);
1284 }
1285 }
1286 }
1287 *pcbEncoded = bytesNeeded;
1288 }
1289 }
1290 return ret;
1291 }
1292
1293 static int BLOBComp(const void *l, const void *r)
1294 {
1295 CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
1296 int ret;
1297
1298 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1299 ret = a->cbData - b->cbData;
1300 return ret;
1301 }
1302
1303 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1304 */
1305 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1306 BYTE *pbEncoded, DWORD *pcbEncoded)
1307 {
1308 BOOL ret;
1309 CRYPT_DER_BLOB *blobs = NULL;
1310
1311 _SEH_TRY
1312 {
1313 DWORD bytesNeeded = 0, lenBytes, i;
1314
1315 blobs = NULL;
1316 ret = TRUE;
1317 if (rdn->cRDNAttr)
1318 {
1319 blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1320 if (!blobs)
1321 ret = FALSE;
1322 else
1323 memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1324 }
1325 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1326 {
1327 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1328 NULL, &blobs[i].cbData);
1329 if (ret)
1330 bytesNeeded += blobs[i].cbData;
1331 }
1332 if (ret)
1333 {
1334 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1335 bytesNeeded += 1 + lenBytes;
1336 if (pbEncoded)
1337 {
1338 if (*pcbEncoded < bytesNeeded)
1339 {
1340 SetLastError(ERROR_MORE_DATA);
1341 ret = FALSE;
1342 }
1343 else
1344 {
1345 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1346 {
1347 blobs[i].pbData = CryptMemAlloc(blobs[i].cbData);
1348 if (!blobs[i].pbData)
1349 ret = FALSE;
1350 else
1351 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1352 &rdn->rgRDNAttr[i], blobs[i].pbData,
1353 &blobs[i].cbData);
1354 }
1355 if (ret)
1356 {
1357 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
1358 BLOBComp);
1359 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1360 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1361 &lenBytes);
1362 pbEncoded += lenBytes;
1363 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1364 {
1365 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
1366 pbEncoded += blobs[i].cbData;
1367 }
1368 }
1369 }
1370 }
1371 *pcbEncoded = bytesNeeded;
1372 }
1373 if (blobs)
1374 {
1375 for (i = 0; i < rdn->cRDNAttr; i++)
1376 CryptMemFree(blobs[i].pbData);
1377 }
1378 }
1379 _SEH_EXCEPT(page_fault)
1380 {
1381 SetLastError(STATUS_ACCESS_VIOLATION);
1382 return FALSE;
1383 }
1384 _SEH_END
1385 CryptMemFree(blobs);
1386 return ret;
1387 }
1388
1389 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1390 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1391 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1392 {
1393 BOOL ret;
1394
1395 _SEH_TRY
1396 {
1397 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1398 DWORD bytesNeeded = 0, lenBytes, size, i;
1399
1400 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1401 ret = TRUE;
1402 for (i = 0; ret && i < info->cRDN; i++)
1403 {
1404 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
1405 &size);
1406 if (ret)
1407 bytesNeeded += size;
1408 }
1409 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1410 bytesNeeded += 1 + lenBytes;
1411 if (ret)
1412 {
1413 if (!pbEncoded)
1414 *pcbEncoded = bytesNeeded;
1415 else
1416 {
1417 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1418 pbEncoded, pcbEncoded, bytesNeeded)))
1419 {
1420 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1421 pbEncoded = *(BYTE **)pbEncoded;
1422 *pbEncoded++ = ASN_SEQUENCEOF;
1423 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1424 &lenBytes);
1425 pbEncoded += lenBytes;
1426 for (i = 0; ret && i < info->cRDN; i++)
1427 {
1428 size = bytesNeeded;
1429 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1430 &info->rgRDN[i], pbEncoded, &size);
1431 if (ret)
1432 {
1433 pbEncoded += size;
1434 bytesNeeded -= size;
1435 }
1436 }
1437 }
1438 }
1439 }
1440 }
1441 _SEH_EXCEPT(page_fault)
1442 {
1443 SetLastError(STATUS_ACCESS_VIOLATION);
1444 ret = FALSE;
1445 }
1446 _SEH_END
1447 return ret;
1448 }
1449
1450 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1451 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1452 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1453 {
1454 BOOL val = *(const BOOL *)pvStructInfo, ret;
1455
1456 TRACE("%d\n", val);
1457
1458 if (!pbEncoded)
1459 {
1460 *pcbEncoded = 3;
1461 ret = TRUE;
1462 }
1463 else if (*pcbEncoded < 3)
1464 {
1465 *pcbEncoded = 3;
1466 SetLastError(ERROR_MORE_DATA);
1467 ret = FALSE;
1468 }
1469 else
1470 {
1471 *pcbEncoded = 3;
1472 *pbEncoded++ = ASN_BOOL;
1473 *pbEncoded++ = 1;
1474 *pbEncoded++ = val ? 0xff : 0;
1475 ret = TRUE;
1476 }
1477 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1478 return ret;
1479 }
1480
1481 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1482 BYTE *pbEncoded, DWORD *pcbEncoded)
1483 {
1484 BOOL ret;
1485 DWORD dataLen;
1486
1487 ret = TRUE;
1488 switch (entry->dwAltNameChoice)
1489 {
1490 case CERT_ALT_NAME_RFC822_NAME:
1491 case CERT_ALT_NAME_DNS_NAME:
1492 case CERT_ALT_NAME_URL:
1493 if (entry->pwszURL)
1494 {
1495 DWORD i;
1496
1497 /* Not + 1: don't encode the NULL-terminator */
1498 dataLen = lstrlenW(entry->pwszURL);
1499 for (i = 0; ret && i < dataLen; i++)
1500 {
1501 if (entry->pwszURL[i] > 0x7f)
1502 {
1503 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1504 ret = FALSE;
1505 *pcbEncoded = i;
1506 }
1507 }
1508 }
1509 else
1510 dataLen = 0;
1511 break;
1512 case CERT_ALT_NAME_IP_ADDRESS:
1513 dataLen = entry->IPAddress.cbData;
1514 break;
1515 case CERT_ALT_NAME_REGISTERED_ID:
1516 /* FIXME: encode OID */
1517 case CERT_ALT_NAME_OTHER_NAME:
1518 case CERT_ALT_NAME_DIRECTORY_NAME:
1519 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
1520 return FALSE;
1521 default:
1522 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1523 return FALSE;
1524 }
1525 if (ret)
1526 {
1527 DWORD bytesNeeded, lenBytes;
1528
1529 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1530 bytesNeeded = 1 + dataLen + lenBytes;
1531 if (!pbEncoded)
1532 *pcbEncoded = bytesNeeded;
1533 else if (*pcbEncoded < bytesNeeded)
1534 {
1535 SetLastError(ERROR_MORE_DATA);
1536 *pcbEncoded = bytesNeeded;
1537 ret = FALSE;
1538 }
1539 else
1540 {
1541 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1542 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1543 pbEncoded += lenBytes;
1544 switch (entry->dwAltNameChoice)
1545 {
1546 case CERT_ALT_NAME_RFC822_NAME:
1547 case CERT_ALT_NAME_DNS_NAME:
1548 case CERT_ALT_NAME_URL:
1549 {
1550 DWORD i;
1551
1552 for (i = 0; i < dataLen; i++)
1553 *pbEncoded++ = (BYTE)entry->pwszURL[i];
1554 break;
1555 }
1556 case CERT_ALT_NAME_IP_ADDRESS:
1557 memcpy(pbEncoded, entry->IPAddress.pbData, dataLen);
1558 break;
1559 }
1560 if (ret)
1561 *pcbEncoded = bytesNeeded;
1562 }
1563 }
1564 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1565 return ret;
1566 }
1567
1568 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1569 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1570 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1571 {
1572 BOOL ret;
1573
1574 _SEH_TRY
1575 {
1576 const CERT_ALT_NAME_INFO *info =
1577 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1578
1579 DWORD bytesNeeded, dataLen, lenBytes, i;
1580
1581 ret = TRUE;
1582 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1583 * can't encode an erroneous entry index if it's bigger than this.
1584 */
1585 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
1586 {
1587 DWORD len;
1588
1589 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
1590 &len);
1591 if (ret)
1592 dataLen += len;
1593 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
1594 {
1595 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1596 * the bad character, now set the index of the bad
1597 * entry
1598 */
1599 *pcbEncoded = (BYTE)i <<
1600 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
1601 }
1602 }
1603 if (ret)
1604 {
1605 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1606 bytesNeeded = 1 + lenBytes + dataLen;
1607 if (!pbEncoded)
1608 {
1609 *pcbEncoded = bytesNeeded;
1610 ret = TRUE;
1611 }
1612 else
1613 {
1614 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1615 pbEncoded, pcbEncoded, bytesNeeded)))
1616 {
1617 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1618 pbEncoded = *(BYTE **)pbEncoded;
1619 *pbEncoded++ = ASN_SEQUENCEOF;
1620 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1621 pbEncoded += lenBytes;
1622 for (i = 0; ret && i < info->cAltEntry; i++)
1623 {
1624 DWORD len = dataLen;
1625
1626 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
1627 pbEncoded, &len);
1628 if (ret)
1629 {
1630 pbEncoded += len;
1631 dataLen -= len;
1632 }
1633 }
1634 }
1635 }
1636 }
1637 }
1638 _SEH_EXCEPT(page_fault)
1639 {
1640 SetLastError(STATUS_ACCESS_VIOLATION);
1641 ret = FALSE;
1642 }
1643 _SEH_END
1644 return ret;
1645 }
1646
1647 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
1648 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1649 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1650 {
1651 BOOL ret;
1652
1653 _SEH_TRY
1654 {
1655 const CERT_BASIC_CONSTRAINTS2_INFO *info =
1656 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
1657 struct AsnEncodeSequenceItem items[2] = { { 0 } };
1658 DWORD cItem = 0;
1659
1660 if (info->fCA)
1661 {
1662 items[cItem].pvStructInfo = &info->fCA;
1663 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1664 cItem++;
1665 }
1666 if (info->fPathLenConstraint)
1667 {
1668 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1669 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1670 cItem++;
1671 }
1672 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1673 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1674 }
1675 _SEH_EXCEPT(page_fault)
1676 {
1677 SetLastError(STATUS_ACCESS_VIOLATION);
1678 ret = FALSE;
1679 }
1680 _SEH_END
1681 return ret;
1682 }
1683
1684 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
1685 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1686 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1687 {
1688 BOOL ret;
1689
1690 _SEH_TRY
1691 {
1692 const BLOBHEADER *hdr =
1693 (const BLOBHEADER *)pvStructInfo;
1694
1695 if (hdr->bType != PUBLICKEYBLOB)
1696 {
1697 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
1698 ret = FALSE;
1699 }
1700 else
1701 {
1702 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
1703 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
1704 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
1705 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
1706 struct AsnEncodeSequenceItem items[] = {
1707 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
1708 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
1709 };
1710
1711 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1712 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1713 pcbEncoded);
1714 }
1715 }
1716 _SEH_EXCEPT(page_fault)
1717 {
1718 SetLastError(STATUS_ACCESS_VIOLATION);
1719 ret = FALSE;
1720 }
1721 _SEH_END
1722 return ret;
1723 }
1724
1725 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
1726 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1727 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1728 {
1729 BOOL ret;
1730
1731 _SEH_TRY
1732 {
1733 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
1734 DWORD bytesNeeded, lenBytes;
1735
1736 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
1737 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
1738
1739 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
1740 bytesNeeded = 1 + lenBytes + blob->cbData;
1741 if (!pbEncoded)
1742 {
1743 *pcbEncoded = bytesNeeded;
1744 ret = TRUE;
1745 }
1746 else
1747 {
1748 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1749 pcbEncoded, bytesNeeded)))
1750 {
1751 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1752 pbEncoded = *(BYTE **)pbEncoded;
1753 *pbEncoded++ = ASN_OCTETSTRING;
1754 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
1755 pbEncoded += lenBytes;
1756 if (blob->cbData)
1757 memcpy(pbEncoded, blob->pbData, blob->cbData);
1758 }
1759 }
1760 }
1761 _SEH_EXCEPT(page_fault)
1762 {
1763 SetLastError(STATUS_ACCESS_VIOLATION);
1764 ret = FALSE;
1765 }
1766 _SEH_END
1767 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1768 return ret;
1769 }
1770
1771 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
1772 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1773 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1774 {
1775 BOOL ret;
1776
1777 _SEH_TRY
1778 {
1779 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1780 DWORD bytesNeeded, lenBytes, dataBytes;
1781 BYTE unusedBits;
1782
1783 /* yep, MS allows cUnusedBits to be >= 8 */
1784 if (!blob->cUnusedBits)
1785 {
1786 dataBytes = blob->cbData;
1787 unusedBits = 0;
1788 }
1789 else if (blob->cbData * 8 > blob->cUnusedBits)
1790 {
1791 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
1792 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
1793 blob->cUnusedBits;
1794 }
1795 else
1796 {
1797 dataBytes = 0;
1798 unusedBits = 0;
1799 }
1800 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
1801 bytesNeeded = 1 + lenBytes + dataBytes + 1;
1802 if (!pbEncoded)
1803 {
1804 *pcbEncoded = bytesNeeded;
1805 ret = TRUE;
1806 }
1807 else
1808 {
1809 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1810 pcbEncoded, bytesNeeded)))
1811 {
1812 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1813 pbEncoded = *(BYTE **)pbEncoded;
1814 *pbEncoded++ = ASN_BITSTRING;
1815 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
1816 pbEncoded += lenBytes;
1817 *pbEncoded++ = unusedBits;
1818 if (dataBytes)
1819 {
1820 BYTE mask = 0xff << unusedBits;
1821
1822 if (dataBytes > 1)
1823 {
1824 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
1825 pbEncoded += dataBytes - 1;
1826 }
1827 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
1828 }
1829 }
1830 }
1831 }
1832 _SEH_EXCEPT(page_fault)
1833 {
1834 SetLastError(STATUS_ACCESS_VIOLATION);
1835 ret = FALSE;
1836 }
1837 _SEH_END
1838 return ret;
1839 }
1840
1841 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
1842 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1843 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1844 {
1845 BOOL ret;
1846
1847 _SEH_TRY
1848 {
1849 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1850 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
1851
1852 ret = TRUE;
1853 if (newBlob.cbData)
1854 {
1855 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
1856 if (newBlob.pbData)
1857 {
1858 DWORD i;
1859
1860 for (i = 0; i < newBlob.cbData; i++)
1861 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
1862 }
1863 else
1864 ret = FALSE;
1865 }
1866 if (ret)
1867 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
1868 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1869 CryptMemFree(newBlob.pbData);
1870 }
1871 _SEH_EXCEPT(page_fault)
1872 {
1873 SetLastError(STATUS_ACCESS_VIOLATION);
1874 ret = FALSE;
1875 }
1876 _SEH_END
1877 return ret;
1878 }
1879
1880 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
1881 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1882 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1883 {
1884 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
1885
1886 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
1887 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1888 }
1889
1890 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
1891 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1892 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1893 {
1894 BOOL ret;
1895
1896 _SEH_TRY
1897 {
1898 DWORD significantBytes, lenBytes;
1899 BYTE padByte = 0, bytesNeeded;
1900 BOOL pad = FALSE;
1901 const CRYPT_INTEGER_BLOB *blob =
1902 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1903
1904 significantBytes = blob->cbData;
1905 if (significantBytes)
1906 {
1907 if (blob->pbData[significantBytes - 1] & 0x80)
1908 {
1909 /* negative, lop off leading (little-endian) 0xffs */
1910 for (; significantBytes > 0 &&
1911 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
1912 ;
1913 if (blob->pbData[significantBytes - 1] < 0x80)
1914 {
1915 padByte = 0xff;
1916 pad = TRUE;
1917 }
1918 }
1919 else
1920 {
1921 /* positive, lop off leading (little-endian) zeroes */
1922 for (; significantBytes > 0 &&
1923 !blob->pbData[significantBytes - 1]; significantBytes--)
1924 ;
1925 if (significantBytes == 0)
1926 significantBytes = 1;
1927 if (blob->pbData[significantBytes - 1] > 0x7f)
1928 {
1929 padByte = 0;
1930 pad = TRUE;
1931 }
1932 }
1933 }
1934 if (pad)
1935 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
1936 else
1937 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
1938 bytesNeeded = 1 + lenBytes + significantBytes;
1939 if (pad)
1940 bytesNeeded++;
1941 if (!pbEncoded)
1942 {
1943 *pcbEncoded = bytesNeeded;
1944 ret = TRUE;
1945 }
1946 else
1947 {
1948 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1949 pcbEncoded, bytesNeeded)))
1950 {
1951 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1952 pbEncoded = *(BYTE **)pbEncoded;
1953 *pbEncoded++ = ASN_INTEGER;
1954 if (pad)
1955 {
1956 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
1957 pbEncoded += lenBytes;
1958 *pbEncoded++ = padByte;
1959 }
1960 else
1961 {
1962 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
1963 pbEncoded += lenBytes;
1964 }
1965 for (; significantBytes > 0; significantBytes--)
1966 *(pbEncoded++) = blob->pbData[significantBytes - 1];
1967 }
1968 }
1969 }
1970 _SEH_EXCEPT(page_fault)
1971 {
1972 SetLastError(STATUS_ACCESS_VIOLATION);
1973 ret = FALSE;
1974 }
1975 _SEH_END
1976 return ret;
1977 }
1978
1979 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
1980 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1981 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1982 {
1983 BOOL ret;
1984
1985 _SEH_TRY
1986 {
1987 DWORD significantBytes, lenBytes;
1988 BYTE bytesNeeded;
1989 BOOL pad = FALSE;
1990 const CRYPT_INTEGER_BLOB *blob =
1991 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
1992
1993 significantBytes = blob->cbData;
1994 if (significantBytes)
1995 {
1996 /* positive, lop off leading (little-endian) zeroes */
1997 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
1998 significantBytes--)
1999 ;
2000 if (significantBytes == 0)
2001 significantBytes = 1;
2002 if (blob->pbData[significantBytes - 1] > 0x7f)
2003 pad = TRUE;
2004 }
2005 if (pad)
2006 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2007 else
2008 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2009 bytesNeeded = 1 + lenBytes + significantBytes;
2010 if (pad)
2011 bytesNeeded++;
2012 if (!pbEncoded)
2013 {
2014 *pcbEncoded = bytesNeeded;
2015 ret = TRUE;
2016 }
2017 else
2018 {
2019 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2020 pcbEncoded, bytesNeeded)))
2021 {
2022 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2023 pbEncoded = *(BYTE **)pbEncoded;
2024 *pbEncoded++ = ASN_INTEGER;
2025 if (pad)
2026 {
2027 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2028 pbEncoded += lenBytes;
2029 *pbEncoded++ = 0;
2030 }
2031 else
2032 {
2033 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2034 pbEncoded += lenBytes;
2035 }
2036 for (; significantBytes > 0; significantBytes--)
2037 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2038 }
2039 }
2040 }
2041 _SEH_EXCEPT(page_fault)
2042 {
2043 SetLastError(STATUS_ACCESS_VIOLATION);
2044 ret = FALSE;
2045 }
2046 _SEH_END
2047 return ret;
2048 }
2049
2050 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2051 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2052 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2053 {
2054 CRYPT_INTEGER_BLOB blob;
2055 BOOL ret;
2056
2057 /* Encode as an unsigned integer, then change the tag to enumerated */
2058 blob.cbData = sizeof(DWORD);
2059 blob.pbData = (BYTE *)pvStructInfo;
2060 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2061 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2062 if (ret && pbEncoded)
2063 {
2064 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2065 pbEncoded = *(BYTE **)pbEncoded;
2066 pbEncoded[0] = ASN_ENUMERATED;
2067 }
2068 return ret;
2069 }
2070
2071 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2072 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2073 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2074 {
2075 BOOL ret;
2076
2077 _SEH_TRY
2078 {
2079 SYSTEMTIME sysTime;
2080 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2081 * temporary buffer because the output buffer is not NULL-terminated.
2082 */
2083 char buf[16];
2084 static const DWORD bytesNeeded = sizeof(buf) - 1;
2085
2086 if (!pbEncoded)
2087 {
2088 *pcbEncoded = bytesNeeded;
2089 ret = TRUE;
2090 }
2091 else
2092 {
2093 /* Sanity check the year, this is a two-digit year format */
2094 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2095 &sysTime);
2096 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2097 {
2098 SetLastError(CRYPT_E_BAD_ENCODE);
2099 ret = FALSE;
2100 }
2101 if (ret)
2102 {
2103 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2104 pbEncoded, pcbEncoded, bytesNeeded)))
2105 {
2106 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2107 pbEncoded = *(BYTE **)pbEncoded;
2108 buf[0] = ASN_UTCTIME;
2109 buf[1] = bytesNeeded - 2;
2110 snprintf(buf + 2, sizeof(buf) - 2,
2111 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2112 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2113 sysTime.wDay, sysTime.wMonth, sysTime.wHour,
2114 sysTime.wMinute, sysTime.wSecond);
2115 memcpy(pbEncoded, buf, bytesNeeded);
2116 }
2117 }
2118 }
2119 }
2120 _SEH_EXCEPT(page_fault)
2121 {
2122 SetLastError(STATUS_ACCESS_VIOLATION);
2123 ret = FALSE;
2124 }
2125 _SEH_END
2126 return ret;
2127 }
2128
2129 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2130 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2131 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2132 {
2133 BOOL ret;
2134
2135 _SEH_TRY
2136 {
2137 SYSTEMTIME sysTime;
2138 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2139 * temporary buffer because the output buffer is not NULL-terminated.
2140 */
2141 char buf[18];
2142 static const DWORD bytesNeeded = sizeof(buf) - 1;
2143
2144 if (!pbEncoded)
2145 {
2146 *pcbEncoded = bytesNeeded;
2147 ret = TRUE;
2148 }
2149 else
2150 {
2151 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2152 &sysTime);
2153 if (ret)
2154 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2155 pcbEncoded, bytesNeeded);
2156 if (ret)
2157 {
2158 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2159 pbEncoded = *(BYTE **)pbEncoded;
2160 buf[0] = ASN_GENERALTIME;
2161 buf[1] = bytesNeeded - 2;
2162 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2163 sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
2164 sysTime.wMinute, sysTime.wSecond);
2165 memcpy(pbEncoded, buf, bytesNeeded);
2166 }
2167 }
2168 }
2169 _SEH_EXCEPT(page_fault)
2170 {
2171 SetLastError(STATUS_ACCESS_VIOLATION);
2172 ret = FALSE;
2173 }
2174 _SEH_END
2175 return ret;
2176 }
2177
2178 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2181 {
2182 BOOL ret;
2183
2184 _SEH_TRY
2185 {
2186 SYSTEMTIME sysTime;
2187
2188 /* Check the year, if it's in the UTCTime range call that encode func */
2189 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2190 return FALSE;
2191 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2192 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2193 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2194 else
2195 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2196 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2197 pcbEncoded);
2198 }
2199 _SEH_EXCEPT(page_fault)
2200 {
2201 SetLastError(STATUS_ACCESS_VIOLATION);
2202 ret = FALSE;
2203 }
2204 _SEH_END
2205 return ret;
2206 }
2207
2208 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2209 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2210 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2211 {
2212 BOOL ret;
2213
2214 _SEH_TRY
2215 {
2216 DWORD bytesNeeded, dataLen, lenBytes, i;
2217 const CRYPT_SEQUENCE_OF_ANY *seq =
2218 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2219
2220 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2221 dataLen += seq->rgValue[i].cbData;
2222 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2223 bytesNeeded = 1 + lenBytes + dataLen;
2224 if (!pbEncoded)
2225 {
2226 *pcbEncoded = bytesNeeded;
2227 ret = TRUE;
2228 }
2229 else
2230 {
2231 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2232 pcbEncoded, bytesNeeded)))
2233 {
2234 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2235 pbEncoded = *(BYTE **)pbEncoded;
2236 *pbEncoded++ = ASN_SEQUENCEOF;
2237 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2238 pbEncoded += lenBytes;
2239 for (i = 0; i < seq->cValue; i++)
2240 {
2241 memcpy(pbEncoded, seq->rgValue[i].pbData,
2242 seq->rgValue[i].cbData);
2243 pbEncoded += seq->rgValue[i].cbData;
2244 }
2245 }
2246 }
2247 }
2248 _SEH_EXCEPT(page_fault)
2249 {
2250 SetLastError(STATUS_ACCESS_VIOLATION);
2251 ret = FALSE;
2252 }
2253 _SEH_END
2254 return ret;
2255 }
2256
2257 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2258 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
2259 void *pvEncoded, DWORD *pcbEncoded)
2260 {
2261 BOOL ret = FALSE;
2262 HMODULE lib = NULL;
2263 CryptEncodeObjectExFunc encodeFunc = NULL;
2264
2265 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
2266 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
2267 pvEncoded, pcbEncoded);
2268
2269 if (!pvEncoded && !pcbEncoded)
2270 {
2271 SetLastError(ERROR_INVALID_PARAMETER);
2272 return FALSE;
2273 }
2274 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2275 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2276 {
2277 SetLastError(ERROR_FILE_NOT_FOUND);
2278 return FALSE;
2279 }
2280
2281 SetLastError(NOERROR);
2282 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
2283 *(BYTE **)pvEncoded = NULL;
2284 if (!HIWORD(lpszStructType))
2285 {
2286 switch (LOWORD(lpszStructType))
2287 {
2288 case (WORD)X509_CERT:
2289 encodeFunc = CRYPT_AsnEncodeCert;
2290 break;
2291 case (WORD)X509_CERT_TO_BE_SIGNED:
2292 encodeFunc = CRYPT_AsnEncodeCertInfo;
2293 break;
2294 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2295 encodeFunc = CRYPT_AsnEncodeCRLInfo;
2296 break;
2297 case (WORD)X509_EXTENSIONS:
2298 encodeFunc = CRYPT_AsnEncodeExtensions;
2299 break;
2300 case (WORD)X509_NAME:
2301 encodeFunc = CRYPT_AsnEncodeName;
2302 break;
2303 case (WORD)X509_PUBLIC_KEY_INFO:
2304 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
2305 break;
2306 case (WORD)X509_ALTERNATE_NAME:
2307 encodeFunc = CRYPT_AsnEncodeAltName;
2308 break;
2309 case (WORD)X509_BASIC_CONSTRAINTS2:
2310 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2311 break;
2312 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2313 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
2314 break;
2315 case (WORD)X509_OCTET_STRING:
2316 encodeFunc = CRYPT_AsnEncodeOctets;
2317 break;
2318 case (WORD)X509_BITS:
2319 case (WORD)X509_KEY_USAGE:
2320 encodeFunc = CRYPT_AsnEncodeBits;
2321 break;
2322 case (WORD)X509_INTEGER:
2323 encodeFunc = CRYPT_AsnEncodeInt;
2324 break;
2325 case (WORD)X509_MULTI_BYTE_INTEGER:
2326 encodeFunc = CRYPT_AsnEncodeInteger;
2327 break;
2328 case (WORD)X509_MULTI_BYTE_UINT:
2329 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
2330 break;
2331 case (WORD)X509_ENUMERATED:
2332 encodeFunc = CRYPT_AsnEncodeEnumerated;
2333 break;
2334 case (WORD)X509_CHOICE_OF_TIME:
2335 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
2336 break;
2337 case (WORD)X509_SEQUENCE_OF_ANY:
2338 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2339 break;
2340 case (WORD)PKCS_UTC_TIME:
2341 encodeFunc = CRYPT_AsnEncodeUtcTime;
2342 break;
2343 default:
2344 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
2345 }
2346 }
2347 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
2348 encodeFunc = CRYPT_AsnEncodeExtensions;
2349 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
2350 encodeFunc = CRYPT_AsnEncodeUtcTime;
2351 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
2352 encodeFunc = CRYPT_AsnEncodeEnumerated;
2353 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2354 encodeFunc = CRYPT_AsnEncodeBits;
2355 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
2356 encodeFunc = CRYPT_AsnEncodeOctets;
2357 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2358 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2359 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2360 encodeFunc = CRYPT_AsnEncodeAltName;
2361 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2362 encodeFunc = CRYPT_AsnEncodeAltName;
2363 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
2364 encodeFunc = CRYPT_AsnEncodeAltName;
2365 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2366 encodeFunc = CRYPT_AsnEncodeAltName;
2367 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2368 encodeFunc = CRYPT_AsnEncodeAltName;
2369 else
2370 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2371 debugstr_a(lpszStructType));
2372 if (!encodeFunc)
2373 encodeFunc = (CryptEncodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
2374 lpszStructType, CRYPT_OID_ENCODE_OBJECT_EX_FUNC, &lib);
2375 if (encodeFunc)
2376 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
2377 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
2378 else
2379 SetLastError(ERROR_FILE_NOT_FOUND);
2380 if (lib)
2381 FreeLibrary(lib);
2382 return ret;
2383 }
2384
2385 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2386 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2387 DWORD *pcbStructInfo)
2388 {
2389 BOOL ret = FALSE;
2390 HMODULE lib;
2391 CryptDecodeObjectFunc pCryptDecodeObject;
2392
2393 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
2394 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
2395 pvStructInfo, pcbStructInfo);
2396
2397 if (!pvStructInfo && !pcbStructInfo)
2398 {
2399 SetLastError(ERROR_INVALID_PARAMETER);
2400 return FALSE;
2401 }
2402
2403 /* Try registered DLL first.. */
2404 pCryptDecodeObject =
2405 (CryptDecodeObjectFunc)CRYPT_GetFunc(dwCertEncodingType,
2406 lpszStructType, CRYPT_OID_DECODE_OBJECT_FUNC, &lib);
2407 if (pCryptDecodeObject)
2408 {
2409 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
2410 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
2411 FreeLibrary(lib);
2412 }
2413 else
2414 {
2415 /* If not, use CryptDecodeObjectEx */
2416 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
2417 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
2418 }
2419 return ret;
2420 }
2421
2422 /* Gets the number of length bytes from the given (leading) length byte */
2423 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2424
2425 /* Helper function to get the encoded length of the data starting at pbEncoded,
2426 * where pbEncoded[0] is the tag. If the data are too short to contain a
2427 * length or if the length is too large for cbEncoded, sets an appropriate
2428 * error code and returns FALSE.
2429 */
2430 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
2431 DWORD *len)
2432 {
2433 BOOL ret;
2434
2435 if (cbEncoded <= 1)
2436 {
2437 SetLastError(CRYPT_E_ASN1_CORRUPT);
2438 ret = FALSE;
2439 }
2440 else if (pbEncoded[1] <= 0x7f)
2441 {
2442 if (pbEncoded[1] + 1 > cbEncoded)
2443 {
2444 SetLastError(CRYPT_E_ASN1_EOD);
2445 ret = FALSE;
2446 }
2447 else
2448 {
2449 *len = pbEncoded[1];
2450 ret = TRUE;
2451 }
2452 }
2453 else
2454 {
2455 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
2456
2457 if (lenLen > sizeof(DWORD) + 1)
2458 {
2459 SetLastError(CRYPT_E_ASN1_LARGE);
2460 ret = FALSE;
2461 }
2462 else if (lenLen + 2 > cbEncoded)
2463 {
2464 SetLastError(CRYPT_E_ASN1_CORRUPT);
2465 ret = FALSE;
2466 }
2467 else
2468 {
2469 DWORD out = 0;
2470
2471 pbEncoded += 2;
2472 while (--lenLen)
2473 {
2474 out <<= 8;
2475 out |= *pbEncoded++;
2476 }
2477 if (out + lenLen + 1 > cbEncoded)
2478 {
2479 SetLastError(CRYPT_E_ASN1_EOD);
2480 ret = FALSE;
2481 }
2482 else
2483 {
2484 *len = out;
2485 ret = TRUE;
2486 }
2487 }
2488 }
2489 return ret;
2490 }
2491
2492 /* Helper function to check *pcbStructInfo, set it to the required size, and
2493 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2494 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2495 * pointer to the newly allocated memory.
2496 */
2497 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
2498 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
2499 DWORD bytesNeeded)
2500 {
2501 BOOL ret = TRUE;
2502
2503 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2504 {
2505 if (pDecodePara && pDecodePara->pfnAlloc)
2506 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
2507 else
2508 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
2509 if (!*(BYTE **)pvStructInfo)
2510 ret = FALSE;
2511 else
2512 *pcbStructInfo = bytesNeeded;
2513 }
2514 else if (*pcbStructInfo < bytesNeeded)
2515 {
2516 *pcbStructInfo = bytesNeeded;
2517 SetLastError(ERROR_MORE_DATA);
2518 ret = FALSE;
2519 }
2520 return ret;
2521 }
2522
2523 /* A few of the members need explanation:
2524 * offset:
2525 * A sequence is decoded into a struct. The offset member is the
2526 * offset of this item within that struct.
2527 * decodeFunc:
2528 * The decoder function to use. If this is NULL, then the member isn't
2529 * decoded, but minSize space is reserved for it.
2530 * minSize:
2531 * The minimum amount of space occupied after decoding. You must set this.
2532 * optional:
2533 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2534 * minSize space is filled with 0 for this member. (Any other failure
2535 * results in CRYPT_AsnDecodeSequence failing.)
2536 * hasPointer, pointerOffset, minSize:
2537 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2538 * the offset within the (outer) struct of the data pointer (or to the
2539 * first data pointer, if more than one exist).
2540 * size:
2541 * Used by CRYPT_AsnDecodeSequence, not for your use.
2542 */
2543 struct AsnDecodeSequenceItem
2544 {
2545 DWORD offset;
2546 CryptDecodeObjectExFunc decodeFunc;
2547 DWORD minSize;
2548 BOOL optional;
2549 BOOL hasPointer;
2550 DWORD pointerOffset;
2551 DWORD size;
2552 };
2553
2554 /* This decodes an arbitrary sequence into a contiguous block of memory
2555 * (basically, a struct.) Each element being decoded is described by a struct
2556 * AsnDecodeSequenceItem, see above.
2557 * startingPointer is an optional pointer to the first place where dynamic
2558 * data will be stored. If you know the starting offset, you may pass it
2559 * here. Otherwise, pass NULL, and one will be inferred from the items.
2560 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2561 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2562 */
2563 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
2564 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
2565 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2566 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
2567 {
2568 BOOL ret;
2569
2570 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
2571 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
2572 startingPointer);
2573
2574 if (pbEncoded[0] == ASN_SEQUENCE)
2575 {
2576 DWORD dataLen;
2577
2578 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2579 {
2580 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2581 DWORD i, bytesNeeded = 0, minSize = 0;
2582 const BYTE *ptr;
2583
2584 ptr = pbEncoded + 1 + lenBytes;
2585 for (i = 0; ret && i < cItem; i++)
2586 {
2587 DWORD nextItemLen;
2588
2589 minSize += items[i].minSize;
2590 if (cbEncoded - (ptr - pbEncoded) != 0)
2591 {
2592 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2593 &nextItemLen)))
2594 {
2595 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2596
2597 if (items[i].decodeFunc)
2598 {
2599 TRACE("sizing item %ld\n", i);
2600 ret = items[i].decodeFunc(dwCertEncodingType, NULL,
2601 ptr, 1 + nextItemLenBytes + nextItemLen,
2602 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
2603 &items[i].size);
2604 if (ret)
2605 {
2606 /* Account for alignment padding */
2607 bytesNeeded += items[i].size;
2608 if (items[i].size % sizeof(DWORD))
2609 bytesNeeded += sizeof(DWORD) -
2610 items[i].size % sizeof(DWORD);
2611 ptr += 1 + nextItemLenBytes + nextItemLen;
2612 }
2613 else if (items[i].optional &&
2614 GetLastError() == CRYPT_E_ASN1_BADTAG)
2615 {
2616 TRACE("skipping optional item %ld\n", i);
2617 bytesNeeded += items[i].minSize;
2618 SetLastError(NOERROR);
2619 ret = TRUE;
2620 }
2621 else
2622 TRACE("item %ld failed: %08lx\n", i,
2623 GetLastError());
2624 }
2625 else
2626 bytesNeeded += items[i].minSize;
2627 }
2628 }
2629 else if (items[i].optional)
2630 bytesNeeded += items[i].minSize;
2631 else
2632 {
2633 SetLastError(CRYPT_E_ASN1_CORRUPT);
2634 ret = FALSE;
2635 }
2636 }
2637 if (cbEncoded - (ptr - pbEncoded) != 0)
2638 {
2639 TRACE("%ld remaining bytes, failing\n", cbEncoded -
2640 (ptr - pbEncoded));
2641 SetLastError(CRYPT_E_ASN1_CORRUPT);
2642 ret = FALSE;
2643 }
2644 if (ret)
2645 {
2646 if (!pvStructInfo)
2647 *pcbStructInfo = bytesNeeded;
2648 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
2649 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
2650 {
2651 BYTE *nextData;
2652
2653 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2654 pvStructInfo = *(BYTE **)pvStructInfo;
2655 if (startingPointer)
2656 nextData = (BYTE *)startingPointer;
2657 else
2658 nextData = (BYTE *)pvStructInfo + minSize;
2659 memset(pvStructInfo, 0, minSize);
2660 ptr = pbEncoded + 1 + lenBytes;
2661 for (i = 0; ret && i < cItem; i++)
2662 {
2663 if (cbEncoded - (ptr - pbEncoded) != 0)
2664 {
2665 DWORD nextItemLen;
2666 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
2667
2668 CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
2669 &nextItemLen);
2670 if (items[i].hasPointer)
2671 {
2672 *(BYTE **)((BYTE *)pvStructInfo +
2673 items[i].pointerOffset) = nextData;
2674 }
2675 if (items[i].decodeFunc)
2676 {
2677 TRACE("decoding item %ld\n", i);
2678 ret = items[i].decodeFunc(dwCertEncodingType,
2679 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
2680 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
2681 (BYTE *)pvStructInfo + items[i].offset,
2682 &items[i].size);
2683 if (!ret)
2684 TRACE("item %ld failed: %08lx\n", i,
2685 GetLastError());
2686 }
2687 else
2688 items[i].size = items[i].minSize;
2689 if (ret)
2690 {
2691 if (items[i].hasPointer &&
2692 items[i].size > items[i].minSize)
2693 {
2694 nextData += items[i].size -
2695 items[i].minSize;
2696 /* align nextData to DWORD boundaries */
2697 if (items[i].size % sizeof(DWORD))
2698 {
2699 nextData += sizeof(DWORD) -
2700 items[i].size % sizeof(DWORD);
2701 }
2702 }
2703 ptr += 1 + nextItemLenBytes + nextItemLen;
2704 }
2705 else if (items[i].optional &&
2706 GetLastError() == CRYPT_E_ASN1_BADTAG)
2707 {
2708 SetLastError(NOERROR);
2709 ret = TRUE;
2710 }
2711 }
2712 else if (!items[i].optional)
2713 {
2714 SetLastError(CRYPT_E_ASN1_CORRUPT);
2715 ret = FALSE;
2716 }
2717 }
2718 }
2719 }
2720 }
2721 }
2722 else
2723 {
2724 SetLastError(CRYPT_E_ASN1_BADTAG);
2725 ret = FALSE;
2726 }
2727 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2728 return ret;
2729 }
2730
2731 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2732 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2733 * to CRYPT_E_ASN1_CORRUPT.
2734 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2735 * set!
2736 */
2737 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
2738 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2739 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2740 {
2741 BOOL ret;
2742 DWORD dataLen;
2743
2744 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2745 {
2746 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2747 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
2748
2749 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2750 bytesNeeded += 1 + lenBytes + dataLen;
2751
2752 if (!pvStructInfo)
2753 *pcbStructInfo = bytesNeeded;
2754 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2755 pvStructInfo, pcbStructInfo, bytesNeeded)))
2756 {
2757 CRYPT_DER_BLOB *blob = (CRYPT_DER_BLOB *)pvStructInfo;
2758
2759 blob->cbData = 1 + lenBytes + dataLen;
2760 if (blob->cbData)
2761 {
2762 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2763 blob->pbData = (BYTE *)pbEncoded;
2764 else
2765 {
2766 assert(blob->pbData);
2767 memcpy(blob->pbData, pbEncoded, blob->cbData);
2768 }
2769 }
2770 else
2771 {
2772 SetLastError(CRYPT_E_ASN1_CORRUPT);
2773 ret = FALSE;
2774 }
2775 }
2776 }
2777 return ret;
2778 }
2779
2780 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2781 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
2782 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2783 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2784 {
2785 BOOL ret;
2786
2787 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2788 pDecodePara, pvStructInfo, *pcbStructInfo);
2789
2790 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2791 * place.
2792 */
2793 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
2794 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2795 pvStructInfo, pcbStructInfo);
2796 if (ret && pvStructInfo)
2797 {
2798 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2799
2800 if (blob->cbData)
2801 {
2802 DWORD i;
2803 BYTE temp;
2804
2805 for (i = 0; i < blob->cbData / 2; i++)
2806 {
2807 temp = blob->pbData[i];
2808 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2809 blob->pbData[blob->cbData - i - 1] = temp;
2810 }
2811 }
2812 }
2813 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2814 return ret;
2815 }
2816
2817 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
2818 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2819 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2820 {
2821 BOOL ret = TRUE;
2822
2823 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2824 pDecodePara, pvStructInfo, *pcbStructInfo);
2825
2826 _SEH_TRY
2827 {
2828 struct AsnDecodeSequenceItem items[] = {
2829 { offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
2830 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2831 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
2832 { offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm),
2833 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2834 FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO,
2835 SignatureAlgorithm.pszObjId), 0 },
2836 { offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
2837 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2838 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
2839 };
2840
2841 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
2842 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
2843 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2844 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2845 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2846 }
2847 _SEH_EXCEPT(page_fault)
2848 {
2849 SetLastError(STATUS_ACCESS_VIOLATION);
2850 ret = FALSE;
2851 }
2852 _SEH_END
2853 return ret;
2854 }
2855
2856 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
2857 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2858 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2859 {
2860 BOOL ret;
2861
2862 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR))
2863 {
2864 DWORD dataLen;
2865
2866 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2867 {
2868 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2869
2870 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2871 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
2872 pvStructInfo, pcbStructInfo);
2873 }
2874 }
2875 else
2876 {
2877 SetLastError(CRYPT_E_ASN1_BADTAG);
2878 ret = FALSE;
2879 }
2880 return ret;
2881 }
2882
2883 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
2884 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2885 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2886 {
2887 BOOL ret;
2888
2889 struct AsnDecodeSequenceItem items[] = {
2890 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
2891 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2892 { offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
2893 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
2894 };
2895
2896 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2897 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2898 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2899 return ret;
2900 }
2901
2902 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
2903 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2904 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2905 {
2906 BOOL ret;
2907
2908 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3))
2909 {
2910 DWORD dataLen;
2911
2912 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2913 {
2914 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2915
2916 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
2917 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
2918 pDecodePara, pvStructInfo, pcbStructInfo);
2919 }
2920 }
2921 else
2922 {
2923 SetLastError(CRYPT_E_ASN1_BADTAG);
2924 ret = FALSE;
2925 }
2926 return ret;
2927 }
2928
2929 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
2930 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2931 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2932 {
2933 BOOL ret = TRUE;
2934
2935 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2936 pDecodePara, pvStructInfo, *pcbStructInfo);
2937
2938 _SEH_TRY
2939 {
2940 struct AsnDecodeSequenceItem items[] = {
2941 { offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
2942 sizeof(DWORD), TRUE, FALSE, 0, 0 },
2943 { offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2944 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2945 SerialNumber.pbData), 0 },
2946 { offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
2947 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO,
2948 SignatureAlgorithm.pszObjId), 0 },
2949 { offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
2950 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2951 Issuer.pbData) },
2952 { offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity,
2953 sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 },
2954 { offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
2955 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
2956 Subject.pbData) },
2957 { offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo,
2958 sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO,
2959 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
2960 { offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal,
2961 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2962 IssuerUniqueId.pbData), 0 },
2963 { offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal,
2964 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO,
2965 SubjectUniqueId.pbData), 0 },
2966 { offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions,
2967 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO,
2968 rgExtension), 0 },
2969 };
2970
2971 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2972 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2973 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2974 }
2975 _SEH_EXCEPT(page_fault)
2976 {
2977 SetLastError(STATUS_ACCESS_VIOLATION);
2978 ret = FALSE;
2979 }
2980 _SEH_END
2981 return ret;
2982 }
2983
2984 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2985 DWORD dwFlags, PCRL_ENTRY entry, DWORD *pcbEntry)
2986 {
2987 BOOL ret;
2988 struct AsnDecodeSequenceItem items[] = {
2989 { offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal,
2990 sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY,
2991 SerialNumber.pbData), 0 },
2992 { offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
2993 sizeof(FILETIME), FALSE, FALSE, 0 },
2994 { offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal,
2995 sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY,
2996 rgExtension), 0 },
2997 };
2998
2999 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
3000 *pcbEntry);
3001
3002 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3003 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3004 NULL, entry, pcbEntry, entry ? entry->SerialNumber.pbData : NULL);
3005 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3006 return ret;
3007 }
3008
3009 typedef struct _WINE_CRL_ENTRIES {
3010 DWORD cCRLEntry;
3011 PCRL_ENTRY rgCRLEntry;
3012 } WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES;
3013
3014 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
3015 * been set prior to calling.
3016 */
3017 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
3018 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3019 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3020 {
3021 BOOL ret;
3022
3023 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3024 pDecodePara, pvStructInfo, *pcbStructInfo);
3025
3026 if (pbEncoded[0] == ASN_SEQUENCEOF)
3027 {
3028 DWORD dataLen, bytesNeeded;
3029
3030 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3031 {
3032 DWORD cCRLEntry = 0;
3033 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3034
3035 bytesNeeded = sizeof(WINE_CRL_ENTRIES);
3036 if (dataLen)
3037 {
3038 const BYTE *ptr;
3039 DWORD size;
3040
3041 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3042 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3043 {
3044 size = 0;
3045 ret = CRYPT_AsnDecodeCRLEntry(ptr,
3046 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3047 if (ret)
3048 {
3049 DWORD nextLen;
3050
3051 cCRLEntry++;
3052 bytesNeeded += size;
3053 ret = CRYPT_GetLen(ptr,
3054 cbEncoded - (ptr - pbEncoded), &nextLen);
3055 if (ret)
3056 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3057 }
3058 }
3059 }
3060 if (ret)
3061 {
3062 if (!pvStructInfo)
3063 *pcbStructInfo = bytesNeeded;
3064 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3065 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3066 {
3067 DWORD size, i;
3068 BYTE *nextData;
3069 const BYTE *ptr;
3070 PWINE_CRL_ENTRIES entries;
3071
3072 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3073 pvStructInfo = *(BYTE **)pvStructInfo;
3074 *pcbStructInfo = bytesNeeded;
3075 entries = (PWINE_CRL_ENTRIES)pvStructInfo;
3076 entries->cCRLEntry = cCRLEntry;
3077 assert(entries->rgCRLEntry);
3078 nextData = (BYTE *)entries->rgCRLEntry +
3079 entries->cCRLEntry * sizeof(CRL_ENTRY);
3080 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3081 i < cCRLEntry && ptr - pbEncoded - 1 - lenBytes <
3082 dataLen; i++)
3083 {
3084 entries->rgCRLEntry[i].SerialNumber.pbData = nextData;
3085 size = bytesNeeded;
3086 ret = CRYPT_AsnDecodeCRLEntry(ptr,
3087 cbEncoded - (ptr - pbEncoded), dwFlags,
3088 &entries->rgCRLEntry[i], &size);
3089 if (ret)
3090 {
3091 DWORD nextLen;
3092
3093 bytesNeeded -= size;
3094 /* Increment nextData by the difference of the
3095 * minimum size and the actual size.
3096 */
3097 if (size > sizeof(CRL_ENTRY))
3098 nextData += size - sizeof(CRL_ENTRY);
3099 ret = CRYPT_GetLen(ptr,
3100 cbEncoded - (ptr - pbEncoded), &nextLen);
3101 if (ret)
3102 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3103 }
3104 }
3105 }
3106 }
3107 }
3108 }
3109 else
3110 {
3111 SetLastError(CRYPT_E_ASN1_BADTAG);
3112 ret = FALSE;
3113 }
3114 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3115 return ret;
3116 }
3117
3118 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
3119 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3121 {
3122 BOOL ret = TRUE;
3123
3124 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3125 pDecodePara, pvStructInfo, *pcbStructInfo);
3126
3127 _SEH_TRY
3128 {
3129 struct AsnDecodeSequenceItem items[] = {
3130 { offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion,
3131 sizeof(DWORD), TRUE, FALSE, 0, 0 },
3132 { offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
3133 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO,
3134 SignatureAlgorithm.pszObjId), 0 },
3135 { offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
3136 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
3137 Issuer.pbData) },
3138 { offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
3139 sizeof(FILETIME), FALSE, FALSE, 0 },
3140 { offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
3141 sizeof(FILETIME), TRUE, FALSE, 0 },
3142 { offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries,
3143 sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO,
3144 rgCRLEntry), 0 },
3145 /* Note that the extensions are ignored by MS, so I'll ignore them too
3146 */
3147 { offsetof(CRL_INFO, cExtension), NULL,
3148 sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
3149 };
3150
3151 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3152 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3153 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3154 }
3155 _SEH_EXCEPT(page_fault)
3156 {
3157 SetLastError(STATUS_ACCESS_VIOLATION);
3158 ret = FALSE;
3159 }
3160 _SEH_END
3161
3162 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3163 return ret;
3164 }
3165
3166 /* Differences between this and CRYPT_AsnDecodeOid:
3167 * - pvStructInfo is a LPSTR *, not an LPSTR
3168 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3169 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3170 * to
3171 */
3172 static BOOL WINAPI CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType,
3173 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3174 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3175 {
3176 BOOL ret;
3177
3178 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3179 pDecodePara, pvStructInfo, *pcbStructInfo);
3180
3181 ret = CRYPT_AsnDecodeOid(pbEncoded, cbEncoded, dwFlags,
3182 pvStructInfo ? *(LPSTR *)pvStructInfo : NULL, pcbStructInfo);
3183 if (ret || GetLastError() == ERROR_MORE_DATA)
3184 *pcbStructInfo += sizeof(LPSTR);
3185 if (ret && pvStructInfo)
3186 TRACE("returning %s\n", debugstr_a(*(LPSTR *)pvStructInfo));
3187 return ret;
3188 }
3189
3190 /* Warning: assumes ext->pszObjId is set ahead of time! */
3191 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
3192 DWORD dwFlags, CERT_EXTENSION *ext, DWORD *pcbExt)
3193 {
3194 struct AsnDecodeSequenceItem items[] = {
3195 { offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper,
3196 sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 },
3197 { offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
3198 sizeof(BOOL), TRUE, FALSE, 0, 0 },
3199 { offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal,
3200 sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION,
3201 Value.pbData) },
3202 };
3203 BOOL ret = TRUE;
3204
3205 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
3206 *pcbExt);
3207
3208 if (ext)
3209 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
3210 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3211 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
3212 ext, pcbExt, ext ? ext->pszObjId : NULL);
3213 if (ext)
3214 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
3215 debugstr_a(ext->pszObjId));
3216 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3217 return ret;
3218 }
3219
3220 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
3221 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3222 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3223 {
3224 BOOL ret = TRUE;
3225
3226 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3227 pDecodePara, pvStructInfo, *pcbStructInfo);
3228
3229 if (pbEncoded[0] == ASN_SEQUENCEOF)
3230 {
3231 DWORD dataLen, bytesNeeded;
3232
3233 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3234 {
3235 DWORD cExtension = 0;
3236 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3237
3238 bytesNeeded = sizeof(CERT_EXTENSIONS);
3239 if (dataLen)
3240 {
3241 const BYTE *ptr;
3242 DWORD size;
3243
3244 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3245 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3246 {
3247 size = 0;
3248 ret = CRYPT_AsnDecodeExtension(ptr,
3249 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3250 if (ret)
3251 {
3252 DWORD nextLen;
3253
3254 cExtension++;
3255 bytesNeeded += size;
3256 ret = CRYPT_GetLen(ptr,
3257 cbEncoded - (ptr - pbEncoded), &nextLen);
3258 if (ret)
3259 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3260 }
3261 }
3262 }
3263 if (ret)
3264 {
3265 if (!pvStructInfo)
3266 *pcbStructInfo = bytesNeeded;
3267 else if (*pcbStructInfo < bytesNeeded)
3268 {
3269 SetLastError(ERROR_MORE_DATA);
3270 *pcbStructInfo = bytesNeeded;
3271 ret = FALSE;
3272 }
3273 else
3274 {
3275 DWORD size, i;
3276 BYTE *nextData;
3277 const BYTE *ptr;
3278 CERT_EXTENSIONS *exts;
3279
3280 *pcbStructInfo = bytesNeeded;
3281 exts = (CERT_EXTENSIONS *)pvStructInfo;
3282 exts->cExtension = cExtension;
3283 assert(exts->rgExtension);
3284 nextData = (BYTE *)exts->rgExtension +
3285 exts->cExtension * sizeof(CERT_EXTENSION);
3286 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3287 i < cExtension && ptr - pbEncoded - 1 - lenBytes <
3288 dataLen; i++)
3289 {
3290 exts->rgExtension[i].pszObjId = (LPSTR)nextData;
3291 size = bytesNeeded;
3292 ret = CRYPT_AsnDecodeExtension(ptr,
3293 cbEncoded - (ptr - pbEncoded), dwFlags,
3294 &exts->rgExtension[i], &size);
3295 if (ret)
3296 {
3297 DWORD nextLen;
3298
3299 bytesNeeded -= size;
3300 if (size > sizeof(CERT_EXTENSION))
3301 nextData += size - sizeof(CERT_EXTENSION);
3302 ret = CRYPT_GetLen(ptr,
3303 cbEncoded - (ptr - pbEncoded), &nextLen);
3304 if (ret)
3305 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3306 }
3307 }
3308 }
3309 }
3310 }
3311 }
3312 else
3313 {
3314 SetLastError(CRYPT_E_ASN1_BADTAG);
3315 ret = FALSE;
3316 }
3317 return ret;
3318 }
3319
3320 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
3321 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3322 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3323 {
3324 BOOL ret = TRUE;
3325
3326 _SEH_TRY
3327 {
3328 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3329 lpszStructType, pbEncoded, cbEncoded,
3330 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3331 if (ret && pvStructInfo)
3332 {
3333 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3334 pcbStructInfo, *pcbStructInfo);
3335 if (ret)
3336 {
3337 CERT_EXTENSIONS *exts;
3338
3339 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3340 pvStructInfo = *(BYTE **)pvStructInfo;
3341 exts = (CERT_EXTENSIONS *)pvStructInfo;
3342 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
3343 sizeof(CERT_EXTENSIONS));
3344 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
3345 lpszStructType, pbEncoded, cbEncoded,
3346 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3347 pcbStructInfo);
3348 }
3349 }
3350 }
3351 _SEH_EXCEPT(page_fault)
3352 {
3353 SetLastError(STATUS_ACCESS_VIOLATION);
3354 ret = FALSE;
3355 }
3356 _SEH_END
3357 return ret;
3358 }
3359
3360 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3361 static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
3362 DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId)
3363 {
3364 BOOL ret = TRUE;
3365
3366 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, pszObjId,
3367 *pcbObjId);
3368
3369 _SEH_TRY
3370 {
3371 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
3372 {
3373 DWORD dataLen;
3374
3375 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3376 {
3377 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3378 DWORD bytesNeeded;
3379
3380 if (dataLen)
3381 {
3382 /* The largest possible string for the first two components
3383 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3384 */
3385 char firstTwo[6];
3386 const BYTE *ptr;
3387
3388 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
3389 pbEncoded[1 + lenBytes] / 40,
3390 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
3391 * 40);
3392 bytesNeeded = strlen(firstTwo) + 1;
3393 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3394 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3395 {
3396 /* large enough for ".4000000" */
3397 char str[9];
3398 int val = 0;
3399
3400 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
3401 (*ptr & 0x80))
3402 {
3403 val <<= 7;
3404 val |= *ptr & 0x7f;
3405 ptr++;
3406 }
3407 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
3408 (*ptr & 0x80))
3409 {
3410 SetLastError(CRYPT_E_ASN1_CORRUPT);
3411 ret = FALSE;
3412 }
3413 else
3414 {
3415 val <<= 7;
3416 val |= *ptr++;
3417 snprintf(str, sizeof(str), ".%d", val);
3418 bytesNeeded += strlen(str);
3419 }
3420 }
3421 if (!pszObjId)
3422 *pcbObjId = bytesNeeded;
3423 else if (*pcbObjId < bytesNeeded)
3424 {
3425 *pcbObjId = bytesNeeded;
3426 SetLastError(ERROR_MORE_DATA);
3427 ret = FALSE;
3428 }
3429 else
3430 {
3431 *pszObjId = 0;
3432 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
3433 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
3434 40) * 40);
3435 pszObjId += strlen(pszObjId);
3436 for (ptr = pbEncoded + 2 + lenBytes; ret &&
3437 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3438 {
3439 int val = 0;
3440
3441 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
3442 (*ptr & 0x80))
3443 {
3444 val <<= 7;
3445 val |= *ptr & 0x7f;
3446 ptr++;
3447 }
3448 val <<= 7;
3449 val |= *ptr++;
3450 sprintf(pszObjId, ".%d", val);
3451 pszObjId += strlen(pszObjId);
3452 }
3453 }
3454 }
3455 else
3456 bytesNeeded = 0;
3457 *pcbObjId = bytesNeeded;
3458 }
3459 }
3460 else
3461 {
3462 SetLastError(CRYPT_E_ASN1_BADTAG);
3463 ret = FALSE;
3464 }
3465 }
3466 _SEH_EXCEPT(page_fault)
3467 {
3468 SetLastError(STATUS_ACCESS_VIOLATION);
3469 ret = FALSE;
3470 }
3471 _SEH_END
3472 return ret;
3473 }
3474
3475 /* Warning: this assumes the address of value->Value.pbData is already set, in
3476 * order to avoid overwriting memory. (In some cases, it may change it, if it
3477 * doesn't copy anything to memory.) Be sure to set it correctly!
3478 */
3479 static BOOL WINAPI CRYPT_AsnDecodeNameValue(const BYTE *pbEncoded,
3480 DWORD cbEncoded, DWORD dwFlags, CERT_NAME_VALUE *value, DWORD *pcbValue)
3481 {
3482 BOOL ret = TRUE;
3483
3484 _SEH_TRY
3485 {
3486 DWORD dataLen;
3487
3488 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3489 {
3490 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3491
3492 switch (pbEncoded[0])
3493 {
3494 case ASN_NUMERICSTRING:
3495 case ASN_PRINTABLESTRING:
3496 case ASN_IA5STRING:
3497 break;
3498 default:
3499 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
3500 SetLastError(OSS_UNIMPLEMENTED);
3501 ret = FALSE;
3502 }
3503 if (ret)
3504 {
3505 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
3506
3507 switch (pbEncoded[0])
3508 {
3509 case ASN_NUMERICSTRING:
3510 case ASN_PRINTABLESTRING:
3511 case ASN_IA5STRING:
3512 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3513 bytesNeeded += dataLen;
3514 break;
3515 }
3516 if (!value)
3517 *pcbValue = bytesNeeded;
3518 else if (*pcbValue < bytesNeeded)
3519 {
3520 *pcbValue = bytesNeeded;
3521 SetLastError(ERROR_MORE_DATA);
3522 ret = FALSE;
3523 }
3524 else
3525 {
3526 *pcbValue = bytesNeeded;
3527 switch (pbEncoded[0])
3528 {
3529 case ASN_NUMERICSTRING:
3530 value->dwValueType = CERT_RDN_NUMERIC_STRING;
3531 break;
3532 case ASN_PRINTABLESTRING:
3533 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
3534 break;
3535 case ASN_IA5STRING:
3536 value->dwValueType = CERT_RDN_IA5_STRING;
3537 break;
3538 }
3539 if (dataLen)
3540 {
3541 switch (pbEncoded[0])
3542 {
3543 case ASN_NUMERICSTRING:
3544 case ASN_PRINTABLESTRING:
3545 case ASN_IA5STRING:
3546 value->Value.cbData = dataLen;
3547 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3548 value->Value.pbData = (BYTE *)pbEncoded + 1 +
3549 lenBytes;
3550 else
3551 {
3552 assert(value->Value.pbData);
3553 memcpy(value->Value.pbData,
3554 pbEncoded + 1 + lenBytes, dataLen);
3555 }
3556 break;
3557 }
3558 }
3559 else
3560 {
3561 value->Value.cbData = 0;
3562 value->Value.pbData = NULL;
3563 }
3564 }
3565 }
3566 }
3567 }
3568 _SEH_EXCEPT(page_fault)
3569 {
3570 SetLastError(STATUS_ACCESS_VIOLATION);
3571 ret = FALSE;
3572 }
3573 _SEH_END
3574 return ret;
3575 }
3576
3577 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3578 * at the moment because of the ASN_CONSTRUCTOR tag.)
3579 */
3580 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded,
3581 DWORD cbEncoded, DWORD dwFlags, CERT_RDN_ATTR *attr, DWORD *pcbAttr)
3582 {
3583 BOOL ret;
3584
3585 _SEH_TRY
3586 {
3587 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCE))
3588 {
3589 DWORD bytesNeeded, dataLen, size;
3590 BYTE lenBytes;
3591
3592 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3593 {
3594 /* The data length must be at least 4, two for the tag and
3595 * length for the OID, and two for the string (assuming both
3596 * have short-form lengths.)
3597 */
3598 if (dataLen < 4)
3599 {
3600 SetLastError(CRYPT_E_ASN1_EOD);
3601 ret = FALSE;
3602 }
3603 else
3604 {
3605 bytesNeeded = sizeof(CERT_RDN_ATTR);
3606 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3607 ret = CRYPT_AsnDecodeOid(pbEncoded + 1 + lenBytes,
3608 cbEncoded - 1 - lenBytes, dwFlags, NULL, &size);
3609 if (ret)
3610 {
3611 /* ugly: need to know the size of the next element of
3612 * the sequence, so get it directly
3613 */
3614 DWORD objIdOfset = 1 + lenBytes, objIdLen,
3615 nameValueOffset = 0;
3616
3617 ret = CRYPT_GetLen(pbEncoded + objIdOfset,
3618 cbEncoded - objIdOfset, &objIdLen);
3619 bytesNeeded += size;
3620 /* hack: like encoding, this takes advantage of the
3621 * fact that the rest of the structure is identical to
3622 * a CERT_NAME_VALUE.
3623 */
3624 if (ret)
3625 {
3626 nameValueOffset = objIdOfset + objIdLen + 1 +
3627 GET_LEN_BYTES(pbEncoded[objIdOfset]);
3628 ret = CRYPT_AsnDecodeNameValue(
3629 pbEncoded + nameValueOffset,
3630 cbEncoded - nameValueOffset, dwFlags, NULL, &size);
3631 }
3632 if (ret)
3633 {
3634 bytesNeeded += size;
3635 if (!attr)
3636 *pcbAttr = bytesNeeded;
3637 else if (*pcbAttr < bytesNeeded)
3638 {
3639 *pcbAttr = bytesNeeded;
3640 SetLastError(ERROR_MORE_DATA);
3641 ret = FALSE;
3642 }
3643 else
3644 {
3645 BYTE *originalData = attr->Value.pbData;
3646
3647 *pcbAttr = bytesNeeded;
3648 /* strange: decode the value first, because it
3649 * has a counted size, and we can store the OID
3650 * after it. Keep track of the original data
3651 * pointer, we'll need to know whether it was
3652 * changed.
3653 */
3654 size = bytesNeeded;
3655 ret = CRYPT_AsnDecodeNameValue(
3656 pbEncoded + nameValueOffset,
3657 cbEncoded - nameValueOffset, dwFlags,
3658 (CERT_NAME_VALUE *)&attr->dwValueType, &size);
3659 if (ret)
3660 {
3661 if (objIdLen)
3662 {
3663 /* if the data were copied to the
3664 * original location, the OID goes
3665 * after. Otherwise it goes in the
3666 * spot originally reserved for the
3667 * data.
3668 */
3669 if (attr->Value.pbData == originalData)
3670 attr->pszObjId =
3671 (LPSTR)(attr->Value.pbData +
3672 attr->Value.cbData);
3673 else
3674 attr->pszObjId =
3675 (LPSTR)originalData;
3676 size = bytesNeeded - size;
3677 ret = CRYPT_AsnDecodeOid(
3678 pbEncoded + objIdOfset,
3679 cbEncoded - objIdOfset,
3680 dwFlags, attr->pszObjId, &size);
3681 }
3682 else
3683 attr->pszObjId = NULL;
3684 }
3685 }
3686 }
3687 }
3688 }
3689 }
3690 }
3691 else
3692 {
3693 SetLastError(CRYPT_E_ASN1_BADTAG);
3694 ret = FALSE;
3695 }
3696 }
3697 _SEH_EXCEPT(page_fault)
3698 {
3699 SetLastError(STATUS_ACCESS_VIOLATION);
3700 ret = FALSE;
3701 }
3702 _SEH_END
3703 return ret;
3704 }
3705
3706 static BOOL WINAPI CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
3707 DWORD dwFlags, CERT_RDN *rdn, DWORD *pcbRdn)
3708 {
3709 BOOL ret = TRUE;
3710
3711 _SEH_TRY
3712 {
3713 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SETOF))
3714 {
3715 DWORD dataLen;
3716
3717 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3718 {
3719 DWORD bytesNeeded, cRDNAttr = 0;
3720 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3721
3722 bytesNeeded = sizeof(CERT_RDN);
3723 if (dataLen)
3724 {
3725 const BYTE *ptr;
3726 DWORD size;
3727
3728 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3729 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3730 {
3731 ret = CRYPT_AsnDecodeRdnAttr(ptr,
3732 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3733 if (ret)
3734 {
3735 DWORD nextLen;
3736
3737 cRDNAttr++;
3738 bytesNeeded += size;
3739 ret = CRYPT_GetLen(ptr,
3740 cbEncoded - (ptr - pbEncoded), &nextLen);
3741 if (ret)
3742 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3743 }
3744 }
3745 }
3746 if (ret)
3747 {
3748 if (!rdn)
3749 *pcbRdn = bytesNeeded;
3750 else if (*pcbRdn < bytesNeeded)
3751 {
3752 *pcbRdn = bytesNeeded;
3753 SetLastError(ERROR_MORE_DATA);
3754 ret = FALSE;
3755 }
3756 else
3757 {
3758 DWORD size, i;
3759 BYTE *nextData;
3760 const BYTE *ptr;
3761
3762 *pcbRdn = bytesNeeded;
3763 rdn->cRDNAttr = cRDNAttr;
3764 rdn->rgRDNAttr = (CERT_RDN_ATTR *)((BYTE *)rdn +
3765 sizeof(CERT_RDN));
3766 nextData = (BYTE *)rdn->rgRDNAttr +
3767 rdn->cRDNAttr * sizeof(CERT_RDN_ATTR);
3768 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3769 i < cRDNAttr && ptr - pbEncoded - 1 - lenBytes <
3770 dataLen; i++)
3771 {
3772 rdn->rgRDNAttr[i].Value.pbData = nextData;
3773 size = bytesNeeded;
3774 ret = CRYPT_AsnDecodeRdnAttr(ptr,
3775 cbEncoded - (ptr - pbEncoded), dwFlags,
3776 &rdn->rgRDNAttr[i], &size);
3777 if (ret)
3778 {
3779 DWORD nextLen;
3780
3781 bytesNeeded -= size;
3782 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3783 * data may not have been copied.
3784 */
3785 if (rdn->rgRDNAttr[i].Value.pbData == nextData)
3786 nextData +=
3787 rdn->rgRDNAttr[i].Value.cbData;
3788 /* Ugly: the OID, if copied, is stored in
3789 * memory after the value, so increment by its
3790 * string length if it's set and points here.
3791 */
3792 if ((const BYTE *)rdn->rgRDNAttr[i].pszObjId
3793 == nextData)
3794 nextData += strlen(
3795 rdn->rgRDNAttr[i].pszObjId) + 1;
3796 ret = CRYPT_GetLen(ptr,
3797 cbEncoded - (ptr - pbEncoded), &nextLen);
3798 if (ret)
3799 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3800 }
3801 }
3802 }
3803 }
3804 }
3805 }
3806 else
3807 {
3808 SetLastError(CRYPT_E_ASN1_BADTAG);
3809 ret = FALSE;
3810 }
3811 }
3812 _SEH_EXCEPT(page_fault)
3813 {
3814 SetLastError(STATUS_ACCESS_VIOLATION);
3815 ret = FALSE;
3816 }
3817 _SEH_END
3818 return ret;
3819 }
3820
3821 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
3822 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3823 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3824 {
3825 BOOL ret = TRUE;
3826
3827 _SEH_TRY
3828 {
3829 if (pbEncoded[0] == (ASN_CONSTRUCTOR | ASN_SEQUENCEOF))
3830 {
3831 DWORD dataLen;
3832
3833 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3834 {
3835 DWORD bytesNeeded, cRDN = 0;
3836 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3837
3838 bytesNeeded = sizeof(CERT_NAME_INFO);
3839 if (dataLen)
3840 {
3841 const BYTE *ptr;
3842
3843 for (ptr = pbEncoded + 1 + lenBytes; ret &&
3844 ptr - pbEncoded - 1 - lenBytes < dataLen; )
3845 {
3846 DWORD size;
3847
3848 ret = CRYPT_AsnDecodeRdn(ptr,
3849 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
3850 if (ret)
3851 {
3852 DWORD nextLen;
3853
3854 cRDN++;
3855 bytesNeeded += size;
3856 ret = CRYPT_GetLen(ptr,
3857 cbEncoded - (ptr - pbEncoded), &nextLen);
3858 if (ret)
3859 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
3860 }
3861 }
3862 }
3863 if (ret)
3864 {
3865 if (!pvStructInfo)
3866 *pcbStructInfo = bytesNeeded;
3867 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3868 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3869 {
3870 CERT_NAME_INFO *info;
3871
3872 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3873 pvStructInfo = *(BYTE **)pvStructInfo;
3874 info = (CERT_NAME_INFO *)pvStructInfo;
3875 info->cRDN = cRDN;
3876 if (info->cRDN == 0)
3877 info->rgRDN = NULL;
3878 else
3879 {
3880 DWORD size, i;
3881 BYTE *nextData;
3882 const BYTE *ptr;
3883
3884 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
3885 sizeof(CERT_NAME_INFO));
3886 nextData = (BYTE *)info->rgRDN +
3887 info->cRDN * sizeof(CERT_RDN);
3888 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
3889 i < cRDN && ptr - pbEncoded - 1 - lenBytes <
3890 dataLen; i++)
3891 {
3892 info->rgRDN[i].rgRDNAttr =
3893 (CERT_RDN_ATTR *)nextData;
3894 size = bytesNeeded;
3895 ret = CRYPT_AsnDecodeRdn(ptr,
3896 cbEncoded - (ptr - pbEncoded), dwFlags,
3897 &info->rgRDN[i], &size);
3898 if (ret)
3899 {
3900 DWORD nextLen;
3901
3902 nextData += size;
3903 bytesNeeded -= size;
3904 ret = CRYPT_GetLen(ptr,
3905 cbEncoded - (ptr - pbEncoded), &nextLen);
3906 if (ret)
3907 ptr += nextLen + 1 +
3908 GET_LEN_BYTES(ptr[1]);
3909 }
3910 }
3911 }
3912 }
3913 }
3914 }
3915 }
3916 else
3917 {
3918 SetLastError(CRYPT_E_ASN1_BADTAG);
3919 ret = FALSE;
3920 }
3921 }
3922 _SEH_EXCEPT(page_fault)
3923 {
3924 SetLastError(STATUS_ACCESS_VIOLATION);
3925 ret = FALSE;
3926 }
3927 _SEH_END
3928 return ret;
3929 }
3930
3931 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
3932 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3933 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3934 {
3935 BOOL ret = TRUE;
3936 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
3937
3938 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3939 pDecodePara, pvStructInfo, *pcbStructInfo);
3940
3941 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3942 bytesNeeded += cbEncoded;
3943 if (!pvStructInfo)
3944 *pcbStructInfo = bytesNeeded;
3945 else if (*pcbStructInfo < bytesNeeded)
3946 {
3947 SetLastError(ERROR_MORE_DATA);
3948 *pcbStructInfo = bytesNeeded;
3949 ret = FALSE;
3950 }
3951 else
3952 {
3953 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
3954
3955 *pcbStructInfo = bytesNeeded;
3956 blob->cbData = cbEncoded;
3957 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3958 blob->pbData = (LPBYTE)pbEncoded;
3959 else
3960 {
3961 assert(blob->pbData);
3962 memcpy(blob->pbData, pbEncoded, blob->cbData);
3963 }
3964 }
3965 return ret;
3966 }
3967
3968 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
3969 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3970 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3971 {
3972 CRYPT_ALGORITHM_IDENTIFIER *algo =
3973 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
3974 BOOL ret = TRUE;
3975 struct AsnDecodeSequenceItem items[] = {
3976 { offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
3977 CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
3978 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
3979 { offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
3980 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3981 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
3982 };
3983
3984 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3985 pDecodePara, pvStructInfo, *pcbStructInfo);
3986
3987 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3988 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3989 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
3990 if (ret && pvStructInfo)
3991 {
3992 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
3993 debugstr_a(algo->pszObjId));
3994 }
3995 return ret;
3996 }
3997
3998 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
3999 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4000 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4001 {
4002 BOOL ret = TRUE;
4003
4004 _SEH_TRY
4005 {
4006 struct AsnDecodeSequenceItem items[] = {
4007 { offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
4008 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4009 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
4010 Algorithm.pszObjId) },
4011 { offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
4012 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
4013 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
4014 };
4015
4016 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4017 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4018 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4019 }
4020 _SEH_EXCEPT(page_fault)
4021 {
4022 SetLastError(STATUS_ACCESS_VIOLATION);
4023 ret = FALSE;
4024 }
4025 _SEH_END
4026 return ret;
4027 }
4028
4029 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
4030 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4031 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4032 {
4033 BOOL ret;
4034
4035 if (cbEncoded < 3)
4036 {
4037 SetLastError(CRYPT_E_ASN1_CORRUPT);
4038 return FALSE;
4039 }
4040 if (pbEncoded[0] != ASN_BOOL)
4041 {
4042 SetLastError(CRYPT_E_ASN1_BADTAG);
4043 return FALSE;
4044 }
4045 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
4046 {
4047 SetLastError(CRYPT_E_ASN1_CORRUPT);
4048 return FALSE;
4049 }
4050 if (pbEncoded[1] > 1)
4051 {
4052 SetLastError(CRYPT_E_ASN1_CORRUPT);
4053 return FALSE;
4054 }
4055 if (!pvStructInfo)
4056 {
4057 *pcbStructInfo = sizeof(BOOL);
4058 ret = TRUE;
4059 }
4060 else if (*pcbStructInfo < sizeof(BOOL))
4061 {
4062 *pcbStructInfo = sizeof(BOOL);
4063 SetLastError(ERROR_MORE_DATA);
4064 ret = FALSE;
4065 }
4066 else
4067 {
4068 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
4069 ret = TRUE;
4070 }
4071 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4072 return ret;
4073 }
4074
4075 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
4076 DWORD dwFlags, CERT_ALT_NAME_ENTRY *entry, DWORD *pcbEntry)
4077 {
4078 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
4079 BOOL ret;
4080
4081 if (cbEncoded < 2)
4082 {
4083 SetLastError(CRYPT_E_ASN1_CORRUPT);
4084 return FALSE;
4085 }
4086 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
4087 {
4088 SetLastError(CRYPT_E_ASN1_BADTAG);
4089 return FALSE;
4090 }
4091 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4092 if (1 + lenBytes > cbEncoded)
4093 {
4094 SetLastError(CRYPT_E_ASN1_CORRUPT);
4095 return FALSE;
4096 }
4097 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4098 {
4099 switch (pbEncoded[0] & ASN_TYPE_MASK)
4100 {
4101 case 1: /* rfc822Name */
4102 case 2: /* dNSName */
4103 case 6: /* uniformResourceIdentifier */
4104 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
4105 break;
4106 case 7: /* iPAddress */
4107 bytesNeeded += dataLen;
4108 break;
4109 case 8: /* registeredID */
4110 /* FIXME: decode as OID */
4111 case 0: /* otherName */
4112 case 4: /* directoryName */
4113 FIXME("stub\n");
4114 SetLastError(CRYPT_E_ASN1_BADTAG);
4115 ret = FALSE;
4116 break;
4117 case 3: /* x400Address, unimplemented */
4118 case 5: /* ediPartyName, unimplemented */
4119 SetLastError(CRYPT_E_ASN1_BADTAG);
4120 ret = FALSE;
4121 break;
4122 default:
4123 SetLastError(CRYPT_E_ASN1_CORRUPT);
4124 ret = FALSE;
4125 }
4126 if (ret)
4127 {
4128 if (!entry)
4129 *pcbEntry = bytesNeeded;
4130 else if (*pcbEntry < bytesNeeded)
4131 {
4132 SetLastError(ERROR_MORE_DATA);
4133 ret = FALSE;
4134 }
4135 else
4136 {
4137 /* MS used values one greater than the asn1 ones.. sigh */
4138 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
4139 switch (pbEncoded[0] & ASN_TYPE_MASK)
4140 {
4141 case 1: /* rfc822Name */
4142 case 2: /* dNSName */
4143 case 6: /* uniformResourceIdentifier */
4144 {
4145 DWORD i;
4146
4147 for (i = 0; i < dataLen; i++)
4148 entry->pwszURL[i] =
4149 (WCHAR)pbEncoded[1 + lenBytes + i];
4150 entry->pwszURL[i] = 0;
4151 break;
4152 }
4153 case 7: /* iPAddress */
4154 /* The next data pointer is in the pwszURL spot, that is,
4155 * the first 4 bytes. Need to move it to the next spot.
4156 */
4157 entry->IPAddress.pbData = (LPBYTE)entry->pwszURL;
4158 entry->IPAddress.cbData = dataLen;
4159 memcpy(entry->IPAddress.pbData, pbEncoded + 1 + lenBytes,
4160 dataLen);
4161 break;
4162 }
4163 }
4164 }
4165 }
4166 return ret;
4167 }
4168
4169 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
4170 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4171 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4172 {
4173 BOOL ret = TRUE;
4174
4175 _SEH_TRY
4176 {
4177 if (pbEncoded[0] == ASN_SEQUENCEOF)
4178 {
4179 DWORD dataLen;
4180
4181 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4182 {
4183 DWORD bytesNeeded, cEntry = 0;
4184 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4185
4186 bytesNeeded = sizeof(CERT_ALT_NAME_INFO);
4187 if (dataLen)
4188 {
4189 const BYTE *ptr;
4190
4191 for (ptr = pbEncoded + 1 + lenBytes; ret &&
4192 ptr - pbEncoded - 1 - lenBytes < dataLen; )
4193 {
4194 DWORD size;
4195
4196 ret = CRYPT_AsnDecodeAltNameEntry(ptr,
4197 cbEncoded - (ptr - pbEncoded), dwFlags, NULL, &size);
4198 if (ret)
4199 {
4200 DWORD nextLen;
4201
4202 cEntry++;
4203 bytesNeeded += size;
4204 ret = CRYPT_GetLen(ptr,
4205 cbEncoded - (ptr - pbEncoded), &nextLen);
4206 if (ret)
4207 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
4208 }
4209 }
4210 }
4211 if (ret)
4212 {
4213 if (!pvStructInfo)
4214 *pcbStructInfo = bytesNeeded;
4215 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4216 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4217 {
4218 CERT_ALT_NAME_INFO *info;
4219
4220 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4221 pvStructInfo = *(BYTE **)pvStructInfo;
4222 info = (CERT_ALT_NAME_INFO *)pvStructInfo;
4223 info->cAltEntry = 0;
4224 if (cEntry == 0)
4225 info->rgAltEntry = NULL;
4226 else
4227 {
4228 DWORD size, i;
4229 BYTE *nextData;
4230 const BYTE *ptr;
4231
4232 info->rgAltEntry =
4233 (CERT_ALT_NAME_ENTRY *)((BYTE *)pvStructInfo +
4234 sizeof(CERT_ALT_NAME_INFO));
4235 nextData = (BYTE *)info->rgAltEntry +
4236 cEntry * sizeof(CERT_ALT_NAME_ENTRY);
4237 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
4238 i < cEntry && ptr - pbEncoded - 1 - lenBytes <
4239 dataLen; i++)
4240 {
4241 info->rgAltEntry[i].pwszURL =
4242 (LPWSTR)nextData;
4243 size = bytesNeeded;
4244 ret = CRYPT_AsnDecodeAltNameEntry(ptr,
4245 cbEncoded - (ptr - pbEncoded), dwFlags,
4246 &info->rgAltEntry[i], &size);
4247 if (ret)
4248 {
4249 DWORD nextLen;
4250
4251 info->cAltEntry++;
4252 nextData += size -
4253 sizeof(CERT_ALT_NAME_ENTRY);
4254 bytesNeeded -= size;
4255 ret = CRYPT_GetLen(ptr,
4256 cbEncoded - (ptr - pbEncoded), &nextLen);
4257 if (ret)
4258 ptr += nextLen + 1 +
4259 GET_LEN_BYTES(ptr[1]);
4260 }
4261 }
4262 }
4263 }
4264 }
4265 }
4266 }
4267 else
4268 {
4269 SetLastError(CRYPT_E_ASN1_BADTAG);
4270 ret = FALSE;
4271 }
4272 }
4273 _SEH_EXCEPT(page_fault)
4274 {
4275 SetLastError(STATUS_ACCESS_VIOLATION);
4276 ret = FALSE;
4277 }
4278 _SEH_END
4279 return ret;
4280 }
4281
4282 struct PATH_LEN_CONSTRAINT
4283 {
4284 BOOL fPathLenConstraint;
4285 DWORD dwPathLenConstraint;
4286 };
4287
4288 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
4289 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4290 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4291 {
4292 BOOL ret = TRUE;
4293
4294 if (cbEncoded)
4295 {
4296 if (pbEncoded[0] == ASN_INTEGER)
4297 {
4298 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
4299
4300 if (!pvStructInfo)
4301 *pcbStructInfo = bytesNeeded;
4302 else if (*pcbStructInfo < bytesNeeded)
4303 {
4304 SetLastError(ERROR_MORE_DATA);
4305 *pcbStructInfo = bytesNeeded;
4306 ret = FALSE;
4307 }
4308 else
4309 {
4310 struct PATH_LEN_CONSTRAINT *constraint =
4311 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
4312 DWORD size = sizeof(constraint->dwPathLenConstraint);
4313
4314 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
4315 pbEncoded, cbEncoded, 0, NULL,
4316 &constraint->dwPathLenConstraint, &size);
4317 if (ret)
4318 constraint->fPathLenConstraint = TRUE;
4319 TRACE("got an int, dwPathLenConstraint is %ld\n",
4320 constraint->dwPathLenConstraint);
4321 }
4322 }
4323 else
4324 {
4325 SetLastError(CRYPT_E_ASN1_CORRUPT);
4326 ret = FALSE;
4327 }
4328 }
4329 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4330 return ret;
4331 }
4332
4333 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
4334 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4335 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4336 {
4337 BOOL ret;
4338
4339 _SEH_TRY
4340 {
4341 struct AsnDecodeSequenceItem items[] = {
4342 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool,
4343 sizeof(BOOL), TRUE, FALSE, 0, 0 },
4344 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint),
4345 CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT),
4346 TRUE, FALSE, 0, 0 },
4347 };
4348
4349 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4350 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4351 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4352 }
4353 _SEH_EXCEPT(page_fault)
4354 {
4355 SetLastError(STATUS_ACCESS_VIOLATION);
4356 ret = FALSE;
4357 }
4358 _SEH_END
4359 return ret;
4360 }
4361
4362 #define RSA1_MAGIC 0x31415352
4363
4364 struct DECODED_RSA_PUB_KEY
4365 {
4366 DWORD pubexp;
4367 CRYPT_INTEGER_BLOB modulus;
4368 };
4369
4370 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
4371 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4372 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4373 {
4374 BOOL ret;
4375
4376 _SEH_TRY
4377 {
4378 struct AsnDecodeSequenceItem items[] = {
4379 { offsetof(struct DECODED_RSA_PUB_KEY, modulus),
4380 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4381 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
4382 0 },
4383 { offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
4384 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4385 };
4386 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
4387 DWORD size = 0;
4388
4389 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4390 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4391 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
4392 if (ret)
4393 {
4394 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4395 decodedKey->modulus.cbData;
4396
4397 if (!pvStructInfo)
4398 {
4399 *pcbStructInfo = bytesNeeded;
4400 ret = TRUE;
4401 }
4402 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4403 pvStructInfo, pcbStructInfo, bytesNeeded)))
4404 {
4405 BLOBHEADER *hdr;
4406 RSAPUBKEY *rsaPubKey;
4407
4408 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4409 pvStructInfo = *(BYTE **)pvStructInfo;
4410 hdr = (BLOBHEADER *)pvStructInfo;
4411 hdr->bType = PUBLICKEYBLOB;
4412 hdr->bVersion = CUR_BLOB_VERSION;
4413 hdr->reserved = 0;
4414 hdr->aiKeyAlg = CALG_RSA_KEYX;
4415 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4416 sizeof(BLOBHEADER));
4417 rsaPubKey->magic = RSA1_MAGIC;
4418 rsaPubKey->pubexp = decodedKey->pubexp;
4419 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4420 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4421 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4422 decodedKey->modulus.cbData);
4423 }
4424 LocalFree(decodedKey);
4425 }
4426 }
4427 _SEH_EXCEPT(page_fault)
4428 {
4429 SetLastError(STATUS_ACCESS_VIOLATION);
4430 ret = FALSE;
4431 }
4432 _SEH_END
4433 return ret;
4434 }
4435
4436 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
4437 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4438 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4439 {
4440 BOOL ret;
4441
4442 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4443 pDecodePara, pvStructInfo, *pcbStructInfo);
4444
4445 if (pbEncoded[0] == ASN_OCTETSTRING)
4446 {
4447 DWORD bytesNeeded, dataLen;
4448
4449 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4450 {
4451 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4452 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4453 else
4454 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4455 if (!pvStructInfo)
4456 *pcbStructInfo = bytesNeeded;
4457 else if (*pcbStructInfo < bytesNeeded)
4458 {
4459 SetLastError(ERROR_MORE_DATA);
4460 *pcbStructInfo = bytesNeeded;
4461 ret = FALSE;
4462 }
4463 else
4464 {
4465 CRYPT_DATA_BLOB *blob;
4466 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4467
4468 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
4469 blob->cbData = dataLen;
4470 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4471 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4472 else
4473 {
4474 assert(blob->pbData);
4475 if (blob->cbData)
4476 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4477 blob->cbData);
4478 }
4479 }
4480 }
4481 }
4482 else
4483 {
4484 SetLastError(CRYPT_E_ASN1_BADTAG);
4485 ret = FALSE;
4486 }
4487 return ret;
4488 }
4489
4490 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
4491 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4492 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4493 {
4494 BOOL ret;
4495
4496 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4497 pDecodePara, pvStructInfo, *pcbStructInfo);
4498
4499 _SEH_TRY
4500 {
4501 DWORD bytesNeeded;
4502
4503 if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
4504 lpszStructType, pbEncoded, cbEncoded,
4505 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4506 {
4507 if (!pvStructInfo)
4508 *pcbStructInfo = bytesNeeded;
4509 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4510 pvStructInfo, pcbStructInfo, bytesNeeded)))
4511 {
4512 CRYPT_DATA_BLOB *blob;
4513
4514 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4515 pvStructInfo = *(BYTE **)pvStructInfo;
4516 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
4517 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4518 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
4519 lpszStructType, pbEncoded, cbEncoded,
4520 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
4521 &bytesNeeded);
4522 }
4523 }
4524 else
4525 {
4526 SetLastError(CRYPT_E_ASN1_BADTAG);
4527 ret = FALSE;
4528 }
4529 }
4530 _SEH_EXCEPT(page_fault)
4531 {
4532 SetLastError(STATUS_ACCESS_VIOLATION);
4533 ret = FALSE;
4534 }
4535 _SEH_END
4536 return ret;
4537 }
4538
4539 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
4540 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4541 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4542 {
4543 BOOL ret;
4544
4545 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
4546 pDecodePara, pvStructInfo, *pcbStructInfo);
4547
4548 if (pbEncoded[0] == ASN_BITSTRING)
4549 {
4550 DWORD bytesNeeded, dataLen;
4551
4552 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4553 {
4554 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4555 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4556 else
4557 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4558 if (!pvStructInfo)
4559 *pcbStructInfo = bytesNeeded;
4560 else if (*pcbStructInfo < bytesNeeded)
4561 {
4562 *pcbStructInfo = bytesNeeded;
4563 SetLastError(ERROR_MORE_DATA);
4564 ret = FALSE;
4565 }
4566 else
4567 {
4568 CRYPT_BIT_BLOB *blob;
4569
4570 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
4571 blob->cbData = dataLen - 1;
4572 blob->cUnusedBits = *(pbEncoded + 1 +
4573 GET_LEN_BYTES(pbEncoded[1]));
4574 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4575 {
4576 blob->pbData = (BYTE *)pbEncoded + 2 +
4577 GET_LEN_BYTES(pbEncoded[1]);
4578 }
4579 else
4580 {
4581 assert(blob->pbData);
4582 if (blob->cbData)
4583 {
4584 BYTE mask = 0xff << blob->cUnusedBits;
4585
4586 memcpy(blob->pbData, pbEncoded + 2 +
4587 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
4588 blob->pbData[blob->cbData - 1] &= mask;
4589 }
4590 }
4591 }
4592 }
4593 }
4594 else
4595 {
4596 SetLastError(CRYPT_E_ASN1_BADTAG);
4597 ret = FALSE;
4598 }
4599 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4600 return ret;
4601 }
4602
4603 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4604 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4605 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4606 {
4607 BOOL ret;
4608
4609 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4610 pDecodePara, pvStructInfo, pcbStructInfo);
4611
4612 _SEH_TRY
4613 {
4614 DWORD bytesNeeded;
4615
4616 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
4617 lpszStructType, pbEncoded, cbEncoded,
4618 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4619 {
4620 if (!pvStructInfo)
4621 *pcbStructInfo = bytesNeeded;
4622 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4623 pvStructInfo, pcbStructInfo, bytesNeeded)))
4624 {
4625 CRYPT_BIT_BLOB *blob;
4626
4627 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4628 pvStructInfo = *(BYTE **)pvStructInfo;
4629 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
4630 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4631 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
4632 lpszStructType, pbEncoded, cbEncoded,
4633 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
4634 &bytesNeeded);
4635 }
4636 }
4637 }
4638 _SEH_EXCEPT(page_fault)
4639 {
4640 SetLastError(STATUS_ACCESS_VIOLATION);
4641 ret = FALSE;
4642 }
4643 _SEH_END
4644 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4645 return ret;
4646 }
4647
4648 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4649 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4650 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4651 {
4652 BOOL ret;
4653
4654 if (!pvStructInfo)
4655 {
4656 *pcbStructInfo = sizeof(int);
4657 return TRUE;
4658 }
4659 _SEH_TRY
4660 {
4661 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
4662 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
4663 DWORD size = sizeof(buf);
4664
4665 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
4666 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4667 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
4668 if (ret)
4669 {
4670 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4671 pvStructInfo, pcbStructInfo, sizeof(int))))
4672 {
4673 int val, i;
4674
4675 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4676 pvStructInfo = *(BYTE **)pvStructInfo;
4677 if (blob->pbData[blob->cbData - 1] & 0x80)
4678 {
4679 /* initialize to a negative value to sign-extend */
4680 val = -1;
4681 }
4682 else
4683 val = 0;
4684 for (i = 0; i < blob->cbData; i++)
4685 {
4686 val <<= 8;
4687 val |= blob->pbData[blob->cbData - i - 1];
4688 }
4689 memcpy(pvStructInfo, &val, sizeof(int));
4690 }
4691 }
4692 else if (GetLastError() == ERROR_MORE_DATA)
4693 SetLastError(CRYPT_E_ASN1_LARGE);
4694 }
4695 _SEH_EXCEPT(page_fault)
4696 {
4697 SetLastError(STATUS_ACCESS_VIOLATION);
4698 ret = FALSE;
4699 }
4700 _SEH_END
4701 return ret;
4702 }
4703
4704 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
4705 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4706 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4707 {
4708 BOOL ret;
4709
4710 if (pbEncoded[0] == ASN_INTEGER)
4711 {
4712 DWORD bytesNeeded, dataLen;
4713
4714 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4715 {
4716 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4717
4718 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4719 if (!pvStructInfo)
4720 *pcbStructInfo = bytesNeeded;
4721 else if (*pcbStructInfo < bytesNeeded)
4722 {
4723 *pcbStructInfo = bytesNeeded;
4724 SetLastError(ERROR_MORE_DATA);
4725 ret = FALSE;
4726 }
4727 else
4728 {
4729 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4730
4731 blob->cbData = dataLen;
4732 assert(blob->pbData);
4733 if (blob->cbData)
4734 {
4735 DWORD i;
4736
4737 for (i = 0; i < blob->cbData; i++)
4738 {
4739 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4740 dataLen - i - 1);
4741 }
4742 }
4743 }
4744 }
4745 }
4746 else
4747 {
4748 SetLastError(CRYPT_E_ASN1_BADTAG);
4749 ret = FALSE;
4750 }
4751 return ret;
4752 }
4753
4754 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4755 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4756 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4757 {
4758 BOOL ret;
4759
4760 _SEH_TRY
4761 {
4762 DWORD bytesNeeded;
4763
4764 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4765 lpszStructType, pbEncoded, cbEncoded,
4766 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4767 {
4768 if (!pvStructInfo)
4769 *pcbStructInfo = bytesNeeded;
4770 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4771 pvStructInfo, pcbStructInfo, bytesNeeded)))
4772 {
4773 CRYPT_INTEGER_BLOB *blob;
4774
4775 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4776 pvStructInfo = *(BYTE **)pvStructInfo;
4777 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4778 blob->pbData = (BYTE *)pvStructInfo +
4779 sizeof(CRYPT_INTEGER_BLOB);
4780 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
4781 lpszStructType, pbEncoded, cbEncoded,
4782 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
4783 &bytesNeeded);
4784 }
4785 }
4786 }
4787 _SEH_EXCEPT(page_fault)
4788 {
4789 SetLastError(STATUS_ACCESS_VIOLATION);
4790 ret = FALSE;
4791 }
4792 _SEH_END
4793 return ret;
4794 }
4795
4796 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
4797 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
4798 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4799 void *pvStructInfo, DWORD *pcbStructInfo)
4800 {
4801 BOOL ret;
4802
4803 if (pbEncoded[0] == ASN_INTEGER)
4804 {
4805 DWORD bytesNeeded, dataLen;
4806
4807 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4808 {
4809 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4810
4811 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4812 if (!pvStructInfo)
4813 *pcbStructInfo = bytesNeeded;
4814 else if (*pcbStructInfo < bytesNeeded)
4815 {
4816 *pcbStructInfo = bytesNeeded;
4817 SetLastError(ERROR_MORE_DATA);
4818 ret = FALSE;
4819 }
4820 else
4821 {
4822 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4823
4824 blob->cbData = dataLen;
4825 assert(blob->pbData);
4826 /* remove leading zero byte if it exists */
4827 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4828 {
4829 blob->cbData--;
4830 blob->pbData++;
4831 }
4832 if (blob->cbData)
4833 {
4834 DWORD i;
4835
4836 for (i = 0; i < blob->cbData; i++)
4837 {
4838 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4839 dataLen - i - 1);
4840 }
4841 }
4842 }
4843 }
4844 }
4845 else
4846 {
4847 SetLastError(CRYPT_E_ASN1_BADTAG);
4848 ret = FALSE;
4849 }
4850 return ret;
4851 }
4852
4853 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4854 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4855 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4856 {
4857 BOOL ret;
4858
4859 _SEH_TRY
4860 {
4861 DWORD bytesNeeded;
4862
4863 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
4864 lpszStructType, pbEncoded, cbEncoded,
4865 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
4866 {
4867 if (!pvStructInfo)
4868 *pcbStructInfo = bytesNeeded;
4869 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4870 pvStructInfo, pcbStructInfo, bytesNeeded)))
4871 {
4872 CRYPT_INTEGER_BLOB *blob;
4873
4874 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4875 pvStructInfo = *(BYTE **)pvStructInfo;
4876 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4877 blob->pbData = (BYTE *)pvStructInfo +
4878 sizeof(CRYPT_INTEGER_BLOB);
4879 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
4880 lpszStructType, pbEncoded, cbEncoded,
4881 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
4882 &bytesNeeded);
4883 }
4884 }
4885 }
4886 _SEH_EXCEPT(page_fault)
4887 {
4888 SetLastError(STATUS_ACCESS_VIOLATION);
4889 ret = FALSE;
4890 }
4891 _SEH_END
4892 return ret;
4893 }
4894
4895 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4896 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4897 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4898 {
4899 BOOL ret;
4900
4901 if (!pvStructInfo)
4902 {
4903 *pcbStructInfo = sizeof(int);
4904 return TRUE;
4905 }
4906 _SEH_TRY
4907 {
4908 if (pbEncoded[0] == ASN_ENUMERATED)
4909 {
4910 unsigned int val = 0, i;
4911
4912 if (cbEncoded <= 1)
4913 {
4914 SetLastError(CRYPT_E_ASN1_EOD);
4915 ret = FALSE;
4916 }
4917 else if (pbEncoded[1] == 0)
4918 {
4919 SetLastError(CRYPT_E_ASN1_CORRUPT);
4920 ret = FALSE;
4921 }
4922 else
4923 {
4924 /* A little strange looking, but we have to accept a sign byte:
4925 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4926 * assuming a small length is okay here, it has to be in short
4927 * form.
4928 */
4929 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4930 {
4931 SetLastError(CRYPT_E_ASN1_LARGE);
4932 return FALSE;
4933 }
4934 for (i = 0; i < pbEncoded[1]; i++)
4935 {
4936 val <<= 8;
4937 val |= pbEncoded[2 + i];
4938 }
4939 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4940 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4941 {
4942 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4943 pvStructInfo = *(BYTE **)pvStructInfo;
4944 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4945 }
4946 }
4947 }
4948 else
4949 {
4950 SetLastError(CRYPT_E_ASN1_BADTAG);
4951 ret = FALSE;
4952 }
4953 }
4954 _SEH_EXCEPT(page_fault)
4955 {
4956 SetLastError(STATUS_ACCESS_VIOLATION);
4957 ret = FALSE;
4958 }
4959 _SEH_END
4960 return ret;
4961 }
4962
4963 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4964 * if it fails.
4965 */
4966 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4967 do { \
4968 BYTE i; \
4969 \
4970 (word) = 0; \
4971 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4972 { \
4973 if (!isdigit(*(pbEncoded))) \
4974 { \
4975 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4976 ret = FALSE; \
4977 } \
4978 else \
4979 { \
4980 (word) *= 10; \
4981 (word) += *(pbEncoded)++ - '0'; \
4982 } \
4983 } \
4984 } while (0)
4985
4986 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4987 SYSTEMTIME *sysTime)
4988 {
4989 BOOL ret;
4990
4991 _SEH_TRY
4992 {
4993 ret = TRUE;
4994 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4995 {
4996 WORD hours, minutes = 0;
4997 BYTE sign = *pbEncoded++;
4998
4999 len--;
5000 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
5001 if (ret && hours >= 24)
5002 {
5003 SetLastError(CRYPT_E_ASN1_CORRUPT);
5004 ret = FALSE;
5005 }
5006 else if (len >= 2)
5007 {
5008 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
5009 if (ret && minutes >= 60)
5010 {
5011 SetLastError(CRYPT_E_ASN1_CORRUPT);
5012 ret = FALSE;
5013 }
5014 }
5015 if (ret)
5016 {
5017 if (sign == '+')
5018 {
5019 sysTime->wHour += hours;
5020 sysTime->wMinute += minutes;
5021 }
5022 else
5023 {
5024 if (hours > sysTime->wHour)
5025 {
5026 sysTime->wDay--;
5027 sysTime->wHour = 24 - (hours - sysTime->wHour);
5028 }
5029 else
5030 sysTime->wHour -= hours;
5031 if (minutes > sysTime->wMinute)
5032 {
5033 sysTime->wHour--;
5034 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
5035 }
5036 else
5037 sysTime->wMinute -= minutes;
5038 }
5039 }
5040 }
5041 }
5042 _SEH_EXCEPT(page_fault)
5043 {
5044 SetLastError(STATUS_ACCESS_VIOLATION);
5045 ret = FALSE;
5046 }
5047 _SEH_END
5048 return ret;
5049 }
5050
5051 #define MIN_ENCODED_TIME_LENGTH 10
5052
5053 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
5054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5056 {
5057 BOOL ret;
5058
5059 if (!pvStructInfo)
5060 {
5061 *pcbStructInfo = sizeof(FILETIME);
5062 return TRUE;
5063 }
5064 _SEH_TRY
5065 {
5066 ret = TRUE;
5067 if (pbEncoded[0] == ASN_UTCTIME)
5068 {
5069 if (cbEncoded <= 1)
5070 {
5071 SetLastError(CRYPT_E_ASN1_EOD);
5072 ret = FALSE;
5073 }
5074 else if (pbEncoded[1] > 0x7f)
5075 {
5076 /* long-form date strings really can't be valid */
5077 SetLastError(CRYPT_E_ASN1_CORRUPT);
5078 ret = FALSE;
5079 }
5080 else
5081 {
5082 SYSTEMTIME sysTime = { 0 };
5083 BYTE len = pbEncoded[1];
5084
5085 if (len < MIN_ENCODED_TIME_LENGTH)
5086 {
5087 SetLastError(CRYPT_E_ASN1_CORRUPT);
5088 ret = FALSE;
5089 }
5090 else
5091 {
5092 pbEncoded += 2;
5093 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
5094 if (sysTime.wYear >= 50)
5095 sysTime.wYear += 1900;
5096 else
5097 sysTime.wYear += 2000;
5098 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5099 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5100 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5101 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
5102 if (ret && len > 0)
5103 {
5104 if (len >= 2 && isdigit(*pbEncoded) &&
5105 isdigit(*(pbEncoded + 1)))
5106 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5107 sysTime.wSecond);
5108 else if (isdigit(*pbEncoded))
5109 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
5110 sysTime.wSecond);
5111 if (ret)
5112 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5113 &sysTime);
5114 }
5115 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
5116 pDecodePara, pvStructInfo, pcbStructInfo,
5117 sizeof(FILETIME))))
5118 {
5119 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5120 pvStructInfo = *(BYTE **)pvStructInfo;
5121 ret = SystemTimeToFileTime(&sysTime,
5122 (FILETIME *)pvStructInfo);
5123 }
5124 }
5125 }
5126 }
5127 else
5128 {
5129 SetLastError(CRYPT_E_ASN1_BADTAG);
5130 ret = FALSE;
5131 }
5132 }
5133 _SEH_EXCEPT(page_fault)
5134 {
5135 SetLastError(STATUS_ACCESS_VIOLATION);
5136 ret = FALSE;
5137 }
5138 _SEH_END
5139 return ret;
5140 }
5141
5142 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
5143 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5144 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5145 {
5146 BOOL ret;
5147
5148 if (!pvStructInfo)
5149 {
5150 *pcbStructInfo = sizeof(FILETIME);
5151 return TRUE;
5152 }
5153 _SEH_TRY
5154 {
5155 ret = TRUE;
5156 if (pbEncoded[0] == ASN_GENERALTIME)
5157 {
5158 if (cbEncoded <= 1)
5159 {
5160 SetLastError(CRYPT_E_ASN1_EOD);
5161 ret = FALSE;
5162 }
5163 else if (pbEncoded[1] > 0x7f)
5164 {
5165 /* long-form date strings really can't be valid */
5166 SetLastError(CRYPT_E_ASN1_CORRUPT);
5167 ret = FALSE;
5168 }
5169 else
5170 {
5171 BYTE len = pbEncoded[1];
5172
5173 if (len < MIN_ENCODED_TIME_LENGTH)
5174 {
5175 SetLastError(CRYPT_E_ASN1_CORRUPT);
5176 ret = FALSE;
5177 }
5178 else
5179 {
5180 SYSTEMTIME sysTime = { 0 };
5181
5182 pbEncoded += 2;
5183 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
5184 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5185 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5186 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5187 if (ret && len > 0)
5188 {
5189 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5190 sysTime.wMinute);
5191 if (ret && len > 0)
5192 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5193 sysTime.wSecond);
5194 if (ret && len > 0 && (*pbEncoded == '.' ||
5195 *pbEncoded == ','))
5196 {
5197 BYTE digits;
5198
5199 pbEncoded++;
5200 len--;
5201 /* workaround macro weirdness */
5202 digits = min(len, 3);
5203 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
5204 sysTime.wMilliseconds);
5205 }
5206 if (ret)
5207 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5208 &sysTime);
5209 }
5210 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
5211 pDecodePara, pvStructInfo, pcbStructInfo,
5212 sizeof(FILETIME))))
5213 {
5214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5215 pvStructInfo = *(BYTE **)pvStructInfo;
5216 ret = SystemTimeToFileTime(&sysTime,
5217 (FILETIME *)pvStructInfo);
5218 }
5219 }
5220 }
5221 }
5222 else
5223 {
5224 SetLastError(CRYPT_E_ASN1_BADTAG);
5225 ret = FALSE;
5226 }
5227 }
5228 _SEH_EXCEPT(page_fault)
5229 {
5230 SetLastError(STATUS_ACCESS_VIOLATION);
5231 ret = FALSE;
5232 }
5233 _SEH_END
5234 return ret;
5235 }
5236
5237 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5238 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5239 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5240 {
5241 BOOL ret;
5242
5243 _SEH_TRY
5244 {
5245 if (pbEncoded[0] == ASN_UTCTIME)
5246 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
5247 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5248 pcbStructInfo);
5249 else if (pbEncoded[0] == ASN_GENERALTIME)
5250 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
5251 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
5252 pvStructInfo, pcbStructInfo);
5253 else
5254 {
5255 SetLastError(CRYPT_E_ASN1_BADTAG);
5256 ret = FALSE;
5257 }
5258 }
5259 _SEH_EXCEPT(page_fault)
5260 {
5261 SetLastError(STATUS_ACCESS_VIOLATION);
5262 ret = FALSE;
5263 }
5264 _SEH_END
5265 return ret;
5266 }
5267
5268 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5269 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5270 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5271 {
5272 BOOL ret = TRUE;
5273
5274 _SEH_TRY
5275 {
5276 if (pbEncoded[0] == ASN_SEQUENCEOF)
5277 {
5278 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5279
5280 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5281 {
5282 BYTE lenBytes;
5283 const BYTE *ptr;
5284
5285 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5286 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5287 cValue = 0;
5288 ptr = pbEncoded + 1 + lenBytes;
5289 remainingLen = dataLen;
5290 while (ret && remainingLen)
5291 {
5292 DWORD nextLen;
5293
5294 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5295 if (ret)
5296 {
5297 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5298
5299 remainingLen -= 1 + nextLenBytes + nextLen;
5300 ptr += 1 + nextLenBytes + nextLen;
5301 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5302 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5303 bytesNeeded += 1 + nextLenBytes + nextLen;
5304 cValue++;
5305 }
5306 }
5307 if (ret)
5308 {
5309 CRYPT_SEQUENCE_OF_ANY *seq;
5310 BYTE *nextPtr;
5311 DWORD i;
5312
5313 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5314 pvStructInfo, pcbStructInfo, bytesNeeded)))
5315 {
5316 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5317 pvStructInfo = *(BYTE **)pvStructInfo;
5318 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
5319 seq->cValue = cValue;
5320 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5321 sizeof(*seq));
5322 nextPtr = (BYTE *)seq->rgValue +
5323 cValue * sizeof(CRYPT_DER_BLOB);
5324 ptr = pbEncoded + 1 + lenBytes;
5325 remainingLen = dataLen;
5326 i = 0;
5327 while (ret && remainingLen)
5328 {
5329 DWORD nextLen;
5330
5331 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5332 if (ret)
5333 {
5334 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5335
5336 seq->rgValue[i].cbData = 1 + nextLenBytes +
5337 nextLen;
5338 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5339 seq->rgValue[i].pbData = (BYTE *)ptr;
5340 else
5341 {
5342 seq->rgValue[i].pbData = nextPtr;
5343 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5344 nextLen);
5345 nextPtr += 1 + nextLenBytes + nextLen;
5346 }
5347 remainingLen -= 1 + nextLenBytes + nextLen;
5348 ptr += 1 + nextLenBytes + nextLen;
5349 i++;
5350 }
5351 }
5352 }
5353 }
5354 }
5355 }
5356 else
5357 {
5358 SetLastError(CRYPT_E_ASN1_BADTAG);
5359 return FALSE;
5360 }
5361 }
5362 _SEH_EXCEPT(page_fault)
5363 {
5364 SetLastError(STATUS_ACCESS_VIOLATION);
5365 ret = FALSE;
5366 }
5367 _SEH_END
5368 return ret;
5369 }
5370
5371 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5372 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5373 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5374 {
5375 BOOL ret = FALSE;
5376 HMODULE lib = NULL;
5377 CryptDecodeObjectExFunc decodeFunc = NULL;
5378
5379 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5380 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5381 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5382
5383 if (!pvStructInfo && !pcbStructInfo)
5384 {
5385 SetLastError(ERROR_INVALID_PARAMETER);
5386 return FALSE;
5387 }
5388 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5389 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5390 {
5391 SetLastError(ERROR_FILE_NOT_FOUND);
5392 return FALSE;
5393 }
5394 if (!cbEncoded)
5395 {
5396 SetLastError(CRYPT_E_ASN1_EOD);
5397 return FALSE;
5398 }
5399 if (cbEncoded > MAX_ENCODED_LEN)
5400 {
5401 SetLastError(CRYPT_E_ASN1_LARGE);
5402 return FALSE;
5403 }
5404
5405 SetLastError(NOERROR);
5406 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5407 *(BYTE **)pvStructInfo = NULL;
5408 if (!HIWORD(lpszStructType))
5409 {
5410 switch (LOWORD(lpszStructType))
5411 {
5412 case (WORD)X509_CERT:
5413 decodeFunc = CRYPT_AsnDecodeCert;
5414 break;
5415 case (WORD)X509_CERT_TO_BE_SIGNED:
5416 decodeFunc = CRYPT_AsnDecodeCertInfo;
5417 break;
5418 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
5419 decodeFunc = CRYPT_AsnDecodeCRLInfo;
5420 break;
5421 case (WORD)X509_EXTENSIONS:
5422 decodeFunc = CRYPT_AsnDecodeExtensions;
5423 break;
5424 case (WORD)X509_NAME:
5425 decodeFunc = CRYPT_AsnDecodeName;
5426 break;
5427 case (WORD)X509_PUBLIC_KEY_INFO:
5428 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5429 break;
5430 case (WORD)X509_ALTERNATE_NAME:
5431 decodeFunc = CRYPT_AsnDecodeAltName;
5432 break;
5433 case (WORD)X509_BASIC_CONSTRAINTS2:
5434 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5435 break;
5436 case (WORD)RSA_CSP_PUBLICKEYBLOB:
5437 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5438 break;
5439 case (WORD)X509_OCTET_STRING:
5440 decodeFunc = CRYPT_AsnDecodeOctets;
5441 break;
5442 case (WORD)X509_BITS:
5443 case (WORD)X509_KEY_USAGE:
5444 decodeFunc = CRYPT_AsnDecodeBits;
5445 break;
5446 case (WORD)X509_INTEGER:
5447 decodeFunc = CRYPT_AsnDecodeInt;
5448 break;
5449 case (WORD)X509_MULTI_BYTE_INTEGER:
5450 decodeFunc = CRYPT_AsnDecodeInteger;
5451 break;
5452 case (WORD)X509_MULTI_BYTE_UINT:
5453 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5454 break;
5455 case (WORD)X509_ENUMERATED:
5456 decodeFunc = CRYPT_AsnDecodeEnumerated;
5457 break;
5458 case (WORD)X509_CHOICE_OF_TIME:
5459 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5460 break;
5461 case (WORD)X509_SEQUENCE_OF_ANY:
5462 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5463 break;
5464 case (WORD)PKCS_UTC_TIME:
5465 decodeFunc = CRYPT_AsnDecodeUtcTime;
5466 break;
5467 default:
5468 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
5469 }
5470 }
5471 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5472 decodeFunc = CRYPT_AsnDecodeExtensions;
5473 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5474 decodeFunc = CRYPT_AsnDecodeUtcTime;
5475 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5476 decodeFunc = CRYPT_AsnDecodeEnumerated;
5477 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5478 decodeFunc = CRYPT_AsnDecodeBits;
5479 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5480 decodeFunc = CRYPT_AsnDecodeOctets;
5481 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5482 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5483 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5484 decodeFunc = CRYPT_AsnDecodeAltName;
5485 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5486 decodeFunc = CRYPT_AsnDecodeAltName;
5487 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5488 decodeFunc = CRYPT_AsnDecodeAltName;
5489 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5490 decodeFunc = CRYPT_AsnDecodeAltName;
5491 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5492 decodeFunc = CRYPT_AsnDecodeAltName;
5493 else
5494 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5495 debugstr_a(lpszStructType));
5496 if (!decodeFunc)
5497 decodeFunc = (CryptDecodeObjectExFunc)CRYPT_GetFunc(dwCertEncodingType,
5498 lpszStructType, CRYPT_OID_DECODE_OBJECT_EX_FUNC, &lib);
5499 if (decodeFunc)
5500 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5501 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5502 else
5503 SetLastError(ERROR_FILE_NOT_FOUND);
5504 if (lib)
5505 FreeLibrary(lib);
5506 return ret;
5507 }
5508
5509 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
5510 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5511 {
5512 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
5513 NULL, 0, NULL, pInfo, pcbInfo);
5514 }
5515
5516 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5517 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5518 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5519 {
5520 BOOL ret;
5521 HCRYPTKEY key;
5522
5523 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
5524 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
5525 pInfo, pcbInfo);
5526
5527 if (!pszPublicKeyObjId)
5528 pszPublicKeyObjId = szOID_RSA_RSA;
5529 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
5530 {
5531 DWORD keySize = 0;
5532
5533 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
5534 if (ret)
5535 {
5536 LPBYTE pubKey = CryptMemAlloc(keySize);
5537
5538 if (pubKey)
5539 {
5540 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
5541 &keySize);
5542 if (ret)
5543 {
5544 DWORD encodedLen = 0;
5545
5546 ret = CryptEncodeObject(dwCertEncodingType,
5547 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
5548 if (ret)
5549 {
5550 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
5551 strlen(pszPublicKeyObjId) + 1 + encodedLen;
5552
5553 if (!pInfo)
5554 *pcbInfo = sizeNeeded;
5555 else if (*pcbInfo < sizeNeeded)
5556 {
5557 SetLastError(ERROR_MORE_DATA);
5558 *pcbInfo = sizeNeeded;
5559 ret = FALSE;
5560 }
5561 else
5562 {
5563 pInfo->Algorithm.pszObjId = (char *)pInfo +
5564 sizeof(CERT_PUBLIC_KEY_INFO);
5565 lstrcpyA(pInfo->Algorithm.pszObjId,
5566 pszPublicKeyObjId);
5567 pInfo->Algorithm.Parameters.cbData = 0;
5568 pInfo->Algorithm.Parameters.pbData = NULL;
5569 pInfo->PublicKey.pbData =
5570 (BYTE *)pInfo->Algorithm.pszObjId
5571 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
5572 pInfo->PublicKey.cbData = encodedLen;
5573 pInfo->PublicKey.cUnusedBits = 0;
5574 ret = CryptEncodeObject(dwCertEncodingType,
5575 RSA_CSP_PUBLICKEYBLOB, pubKey,
5576 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
5577 }
5578 }
5579 }
5580 CryptMemFree(pubKey);
5581 }
5582 else
5583 ret = FALSE;
5584 }
5585 CryptDestroyKey(key);
5586 }
5587 return ret;
5588 }
5589
5590 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5591 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
5592 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
5593
5594 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
5595 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
5596 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
5597 {
5598 BOOL ret;
5599 ExportPublicKeyInfoExFunc exportFunc = NULL;
5600 HMODULE lib = NULL;
5601
5602 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
5603 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
5604 pInfo, pcbInfo);
5605
5606 if (!hCryptProv)
5607 {
5608 SetLastError(ERROR_INVALID_PARAMETER);
5609 return FALSE;
5610 }
5611
5612 if (pszPublicKeyObjId)
5613 exportFunc = CRYPT_GetFunc(dwCertEncodingType, pszPublicKeyObjId,
5614 CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC, &lib);
5615 if (!exportFunc)
5616 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
5617 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
5618 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
5619 if (lib)
5620 FreeLibrary(lib);
5621 return ret;
5622 }
5623
5624 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
5625 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
5626 {
5627 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
5628 0, 0, NULL, phKey);
5629 }
5630
5631 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5632 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5633 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5634 {
5635 BOOL ret;
5636 DWORD pubKeySize = 0;
5637
5638 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
5639 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5640
5641 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5642 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
5643 if (ret)
5644 {
5645 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
5646
5647 if (pubKey)
5648 {
5649 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
5650 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
5651 &pubKeySize);
5652 if (ret)
5653 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
5654 phKey);
5655 CryptMemFree(pubKey);
5656 }
5657 else
5658 ret = FALSE;
5659 }
5660 return ret;
5661 }
5662
5663 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
5664 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5665 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
5666
5667 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
5668 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
5669 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
5670 {
5671 BOOL ret;
5672 ImportPublicKeyInfoExFunc importFunc = NULL;
5673 HMODULE lib = NULL;
5674
5675 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
5676 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
5677
5678 importFunc = CRYPT_GetFunc(dwCertEncodingType, pInfo->Algorithm.pszObjId,
5679 CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, &lib);
5680 if (!importFunc)
5681 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
5682 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
5683 pvAuxInfo, phKey);
5684 if (lib)
5685 FreeLibrary(lib);
5686 return ret;
5687 }