2 * Copyright 2002 Mike McCormack for CodeWeavers
3 * Copyright 2005 Juan Lang
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.
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.
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
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.
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.)
29 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
32 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 /* a few asn.1 tags we need */
54 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
55 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
56 #define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
57 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
58 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
59 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
60 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
61 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
62 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
63 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
65 #define ASN_FLAGS_MASK 0xf0
66 #define ASN_TYPE_MASK 0x0f
68 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
70 static const WCHAR szDllName
[] = { 'D','l','l',0 };
72 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
74 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
75 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
76 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
77 DWORD
, DWORD
, void *, DWORD
*);
78 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
79 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
81 /* Prototypes for built-in encoders/decoders. They follow the Ex style
82 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
83 * built-in functions, but the parameters are retained to simplify
84 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
85 * external DLLs that follow these signatures.
86 * FIXME: some built-in functions are suitable to be called directly by
87 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
88 * and memory allocation if requested), others are only suitable to be called
89 * internally. Comment which are which.
91 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
92 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
93 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
94 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
95 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
96 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
99 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
100 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
101 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
102 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
104 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
105 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
106 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
107 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
108 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
109 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
110 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
111 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
112 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
113 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
114 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
115 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
116 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
117 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
118 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
122 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
123 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
124 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
125 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
126 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
127 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
128 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
129 * time, doesn't do memory allocation, and doesn't do exception handling.
130 * (This isn't intended to be the externally-called one.)
132 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
133 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
134 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
135 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
136 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
);
137 /* Assumes algo->Parameters.pbData is set ahead of time */
138 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
139 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
140 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
141 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
142 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
143 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
144 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
145 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
146 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
147 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
148 * member has been initialized, doesn't do exception handling, and doesn't do
151 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
152 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
153 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
154 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
155 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
156 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
157 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
158 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
159 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
160 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
161 * member has been initialized, doesn't do exception handling, and doesn't do
164 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
165 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
166 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
168 /* filter for page-fault exceptions */
169 static WINE_EXCEPTION_FILTER(page_fault
)
171 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
172 return EXCEPTION_EXECUTE_HANDLER
;
173 return EXCEPTION_CONTINUE_SEARCH
;
176 static char *CRYPT_GetKeyName(DWORD dwEncodingType
, LPCSTR pszFuncName
,
179 static const char szEncodingTypeFmt
[] =
180 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
182 char numericOID
[7]; /* enough for "#65535" */
186 /* MSDN says the encoding type is a mask, but it isn't treated that way.
187 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
188 * "EncodingType 2" would be expected if it were a mask. Instead native
189 * stores values in "EncodingType 3".
193 snprintf(numericOID
, sizeof(numericOID
), "#%d", LOWORD(pszOID
));
199 /* This is enough: the lengths of the two string parameters are explicitly
200 * counted, and we need up to five additional characters for the encoding
201 * type. These are covered by the "%d", "%s", and "%s" characters in the
202 * format specifier that are removed by sprintf.
204 len
= sizeof(szEncodingTypeFmt
) + lstrlenA(pszFuncName
) + lstrlenA(oid
);
205 szKey
= HeapAlloc(GetProcessHeap(), 0, len
);
207 sprintf(szKey
, szEncodingTypeFmt
, dwEncodingType
, pszFuncName
, oid
);
211 BOOL WINAPI
CryptRegisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
212 LPCSTR pszOID
, LPCWSTR pwszDll
, LPCSTR pszOverrideFuncName
)
218 TRACE("%lx %s %s %s %s\n", dwEncodingType
, pszFuncName
, pszOID
,
219 debugstr_w(pwszDll
), pszOverrideFuncName
);
221 /* This only registers functions for encoding certs, not messages */
222 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
225 /* Native does nothing pwszDll is NULL */
229 /* I'm not matching MS bug for bug here, because I doubt any app depends on
231 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
232 * it creates would never be used
233 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
234 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
236 if (!pszFuncName
|| !pszOID
)
238 SetLastError(ERROR_INVALID_PARAMETER
);
242 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
243 TRACE("Key name is %s\n", debugstr_a(szKey
));
248 r
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
249 HeapFree(GetProcessHeap(), 0, szKey
);
250 if(r
!= ERROR_SUCCESS
)
253 /* write the values */
254 if (pszOverrideFuncName
)
255 RegSetValueExA(hKey
, "FuncName", 0, REG_SZ
, (const BYTE
*)pszOverrideFuncName
,
256 lstrlenA(pszOverrideFuncName
) + 1);
257 RegSetValueExW(hKey
, szDllName
, 0, REG_SZ
, (const BYTE
*) pwszDll
,
258 (lstrlenW(pwszDll
) + 1) * sizeof (WCHAR
));
264 BOOL WINAPI
CryptUnregisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
270 TRACE("%lx %s %s\n", dwEncodingType
, pszFuncName
, pszOID
);
272 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
275 if (!pszFuncName
|| !pszOID
)
277 SetLastError(ERROR_INVALID_PARAMETER
);
281 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
282 rc
= RegDeleteKeyA(HKEY_LOCAL_MACHINE
, szKey
);
283 HeapFree(GetProcessHeap(), 0, szKey
);
286 return rc
? FALSE
: TRUE
;
289 BOOL WINAPI
CryptGetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
290 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD
*pdwValueType
, BYTE
*pbValueData
,
297 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType
, debugstr_a(pszFuncName
),
298 debugstr_a(pszOID
), debugstr_w(pwszValueName
), pdwValueType
, pbValueData
,
301 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
304 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
306 SetLastError(ERROR_INVALID_PARAMETER
);
310 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
311 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
312 HeapFree(GetProcessHeap(), 0, szKey
);
317 rc
= RegQueryValueExW(hKey
, pwszValueName
, NULL
, pdwValueType
,
318 pbValueData
, pcbValueData
);
323 return rc
? FALSE
: TRUE
;
326 BOOL WINAPI
CryptSetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
327 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD dwValueType
,
328 const BYTE
*pbValueData
, DWORD cbValueData
)
334 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType
, debugstr_a(pszFuncName
),
335 debugstr_a(pszOID
), debugstr_w(pwszValueName
), dwValueType
, pbValueData
,
338 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
341 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
343 SetLastError(ERROR_INVALID_PARAMETER
);
347 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
348 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
349 HeapFree(GetProcessHeap(), 0, szKey
);
354 rc
= RegSetValueExW(hKey
, pwszValueName
, 0, dwValueType
, pbValueData
,
360 return rc
? FALSE
: TRUE
;
363 /* Gets the registered function named szFuncName for dwCertEncodingType and
364 * lpszStructType, or NULL if one could not be found. *lib will be set to the
365 * handle of the module it's in, or NULL if no module was loaded. If the
366 * return value is NULL, *lib will also be NULL, to simplify error handling.
368 static void *CRYPT_GetFunc(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
369 LPCSTR szFuncName
, HMODULE
*lib
)
372 char *szKey
= CRYPT_GetKeyName(dwCertEncodingType
, szFuncName
,
374 const char *funcName
;
377 DWORD type
, size
= 0;
379 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType
, debugstr_a(lpszStructType
),
380 debugstr_a(szFuncName
), lib
);
383 r
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
384 HeapFree(GetProcessHeap(), 0, szKey
);
385 if(r
!= ERROR_SUCCESS
)
388 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, NULL
, &size
);
389 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
391 funcName
= HeapAlloc(GetProcessHeap(), 0, size
);
392 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, (LPBYTE
)funcName
,
396 funcName
= szFuncName
;
397 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, NULL
, &size
);
398 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
400 LPWSTR dllName
= HeapAlloc(GetProcessHeap(), 0, size
);
402 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, (LPBYTE
)dllName
,
404 *lib
= LoadLibraryW(dllName
);
407 ret
= GetProcAddress(*lib
, funcName
);
410 /* Unload the library, the caller doesn't want to unload it
411 * when the return value is NULL.
417 HeapFree(GetProcessHeap(), 0, dllName
);
419 if (funcName
!= szFuncName
)
420 HeapFree(GetProcessHeap(), 0, (char *)funcName
);
421 TRACE("returning %p\n", ret
);
425 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
426 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
430 CryptEncodeObjectFunc pCryptEncodeObject
;
432 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
433 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
436 if (!pbEncoded
&& !pcbEncoded
)
438 SetLastError(ERROR_INVALID_PARAMETER
);
442 /* Try registered DLL first.. */
444 (CryptEncodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
445 lpszStructType
, "CryptEncodeObject", &lib
);
446 if (pCryptEncodeObject
)
448 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
449 pvStructInfo
, pbEncoded
, pcbEncoded
);
454 /* If not, use CryptEncodeObjectEx */
455 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
456 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
461 /* Helper function to check *pcbEncoded, set it to the required size, and
462 * optionally to allocate memory. Assumes pbEncoded is not NULL.
463 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
464 * pointer to the newly allocated memory.
466 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
467 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
472 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
474 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
475 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
477 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
478 if (!*(BYTE
**)pbEncoded
)
481 *pcbEncoded
= bytesNeeded
;
483 else if (bytesNeeded
> *pcbEncoded
)
485 *pcbEncoded
= bytesNeeded
;
486 SetLastError(ERROR_MORE_DATA
);
492 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
494 DWORD bytesNeeded
, significantBytes
= 0;
502 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
503 temp
<<= 8, significantBytes
--)
505 bytesNeeded
= significantBytes
+ 1;
509 *pcbEncoded
= bytesNeeded
;
512 if (*pcbEncoded
< bytesNeeded
)
514 SetLastError(ERROR_MORE_DATA
);
518 *pbEncoded
= (BYTE
)len
;
523 *pbEncoded
++ = significantBytes
| 0x80;
524 for (i
= 0; i
< significantBytes
; i
++)
526 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
530 *pcbEncoded
= bytesNeeded
;
534 struct AsnEncodeSequenceItem
536 const void *pvStructInfo
;
537 CryptEncodeObjectExFunc encodeFunc
;
538 DWORD size
; /* used during encoding, not for your use */
541 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
542 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
543 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
546 DWORD i
, dataLen
= 0;
548 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
549 pbEncoded
, *pcbEncoded
);
550 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
552 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
553 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
554 NULL
, &items
[i
].size
);
555 dataLen
+= items
[i
].size
;
559 DWORD lenBytes
, bytesNeeded
;
561 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
562 bytesNeeded
= 1 + lenBytes
+ dataLen
;
564 *pcbEncoded
= bytesNeeded
;
567 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
568 pcbEncoded
, bytesNeeded
)))
570 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
571 pbEncoded
= *(BYTE
**)pbEncoded
;
572 *pbEncoded
++ = ASN_SEQUENCE
;
573 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
574 pbEncoded
+= lenBytes
;
575 for (i
= 0; ret
&& i
< cItem
; i
++)
577 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
578 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
579 NULL
, pbEncoded
, &items
[i
].size
);
580 pbEncoded
+= items
[i
].size
;
585 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
589 struct AsnConstructedItem
592 const void *pvStructInfo
;
593 CryptEncodeObjectExFunc encodeFunc
;
596 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
597 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
598 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
601 const struct AsnConstructedItem
*item
=
602 (const struct AsnConstructedItem
*)pvStructInfo
;
605 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
606 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
608 DWORD dataLen
, bytesNeeded
;
610 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
611 bytesNeeded
= 1 + dataLen
+ len
;
613 *pcbEncoded
= bytesNeeded
;
614 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
615 pbEncoded
, pcbEncoded
, bytesNeeded
)))
617 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
618 pbEncoded
= *(BYTE
**)pbEncoded
;
619 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
620 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
621 pbEncoded
+= dataLen
;
622 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
623 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
630 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
631 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
632 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
634 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
637 /* CERT_V1 is not encoded */
645 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
647 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
648 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
653 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
654 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
655 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
657 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
662 *pcbEncoded
= blob
->cbData
;
665 else if (*pcbEncoded
< blob
->cbData
)
667 *pcbEncoded
= blob
->cbData
;
668 SetLastError(ERROR_MORE_DATA
);
674 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
675 *pcbEncoded
= blob
->cbData
;
681 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
682 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
683 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
686 /* This has two filetimes in a row, a NotBefore and a NotAfter */
687 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
688 struct AsnEncodeSequenceItem items
[] = {
689 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
690 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
693 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
694 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
699 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
700 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
701 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
704 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
705 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
707 struct AsnEncodeSequenceItem items
[] = {
708 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
709 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
712 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
713 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
718 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
719 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
720 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
726 const CERT_PUBLIC_KEY_INFO
*info
=
727 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
728 struct AsnEncodeSequenceItem items
[] = {
729 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
730 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
733 TRACE("Encoding public key with OID %s\n",
734 debugstr_a(info
->Algorithm
.pszObjId
));
735 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
736 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
741 SetLastError(STATUS_ACCESS_VIOLATION
);
748 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
749 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
750 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
756 const CERT_SIGNED_CONTENT_INFO
*info
=
757 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
758 struct AsnEncodeSequenceItem items
[] = {
759 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
760 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
761 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
764 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
765 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
766 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
767 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
772 SetLastError(STATUS_ACCESS_VIOLATION
);
779 /* Like in Windows, this blithely ignores the validity of the passed-in
780 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
781 * decode properly, see CRYPT_AsnDecodeCertInfo.
783 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
784 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
785 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
791 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
792 struct AsnEncodeSequenceItem items
[10] = {
793 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
794 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
795 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
796 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
797 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
798 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
799 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
802 struct AsnConstructedItem constructed
[3] = { { 0 } };
803 DWORD cItem
= 7, cConstructed
= 0;
805 if (info
->IssuerUniqueId
.cbData
)
807 constructed
[cConstructed
].tag
= 1;
808 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
809 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
810 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
811 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
815 if (info
->SubjectUniqueId
.cbData
)
817 constructed
[cConstructed
].tag
= 2;
818 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
819 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
820 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
821 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
825 if (info
->cExtension
)
827 constructed
[cConstructed
].tag
= 3;
828 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
829 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
830 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
831 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
836 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
837 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
841 SetLastError(STATUS_ACCESS_VIOLATION
);
848 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
849 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
851 struct AsnEncodeSequenceItem items
[3] = {
852 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
853 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
859 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
861 if (entry
->cExtension
)
863 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
864 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
868 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
869 pbEncoded
, pcbEncoded
);
871 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
875 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
876 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
877 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
879 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
880 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
881 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
882 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
885 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
889 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
893 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
894 bytesNeeded
= 1 + lenBytes
+ dataLen
;
896 *pcbEncoded
= bytesNeeded
;
899 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
900 pcbEncoded
, bytesNeeded
)))
902 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
903 pbEncoded
= *(BYTE
**)pbEncoded
;
904 *pbEncoded
++ = ASN_SEQUENCEOF
;
905 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
906 pbEncoded
+= lenBytes
;
907 for (i
= 0; i
< cCRLEntry
; i
++)
909 DWORD size
= dataLen
;
911 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
920 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
921 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
922 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
924 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
927 /* CRL_V1 is not encoded */
934 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
935 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
939 /* Like in Windows, this blithely ignores the validity of the passed-in
940 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
941 * decode properly, see CRYPT_AsnDecodeCRLInfo.
943 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
944 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
945 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
951 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
952 struct AsnEncodeSequenceItem items
[7] = {
953 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
954 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
955 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
956 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
959 struct AsnConstructedItem constructed
= { 0 };
962 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
964 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
965 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
970 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
971 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
974 if (info
->cExtension
)
976 /* FIXME: is this really constructed? if so, is this the right tag?
979 constructed
.pvStructInfo
= &info
->cExtension
;
980 constructed
.encodeFunc
= CRYPT_AsnEncodeExtensions
;
981 items
[cItem
].pvStructInfo
= &constructed
;
982 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
986 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
987 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
991 SetLastError(STATUS_ACCESS_VIOLATION
);
998 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
1002 struct AsnEncodeSequenceItem items
[3] = {
1003 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1009 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
1013 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
1014 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1017 items
[cItem
].pvStructInfo
= &ext
->Value
;
1018 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1021 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
1022 pbEncoded
, pcbEncoded
);
1023 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1027 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
1028 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1029 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1035 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1036 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
1039 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
1043 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
1047 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1048 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1050 *pcbEncoded
= bytesNeeded
;
1053 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1054 pcbEncoded
, bytesNeeded
)))
1056 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1057 pbEncoded
= *(BYTE
**)pbEncoded
;
1058 *pbEncoded
++ = ASN_SEQUENCEOF
;
1059 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1060 pbEncoded
+= lenBytes
;
1061 for (i
= 0; i
< exts
->cExtension
; i
++)
1063 DWORD size
= dataLen
;
1065 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
1073 __EXCEPT(page_fault
)
1075 SetLastError(STATUS_ACCESS_VIOLATION
);
1082 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
1083 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1084 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1086 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
1087 DWORD bytesNeeded
= 0, lenBytes
;
1092 TRACE("%s\n", debugstr_a(pszObjId
));
1099 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
1101 SetLastError(CRYPT_E_ASN1_ERROR
);
1105 firstByte
= val1
* 40 + val2
;
1106 ptr
= pszObjId
+ firstPos
;
1111 /* note I assume each component is at most 32-bits long in base 2 */
1112 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
1114 if (val1
>= 0x10000000)
1116 else if (val1
>= 0x200000)
1118 else if (val1
>= 0x4000)
1120 else if (val1
>= 0x80)
1130 SetLastError(CRYPT_E_ASN1_ERROR
);
1134 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1138 bytesNeeded
+= 1 + lenBytes
;
1141 if (*pcbEncoded
< bytesNeeded
)
1143 SetLastError(ERROR_MORE_DATA
);
1148 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
1149 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
1150 pbEncoded
+= lenBytes
;
1156 *pbEncoded
++ = firstByte
;
1157 ptr
= pszObjId
+ firstPos
;
1160 sscanf(ptr
, "%d%n", &val
, &pos
);
1162 unsigned char outBytes
[5];
1165 if (val
>= 0x10000000)
1167 else if (val
>= 0x200000)
1169 else if (val
>= 0x4000)
1171 else if (val
>= 0x80)
1175 for (i
= numBytes
; i
> 0; i
--)
1177 outBytes
[i
- 1] = val
& 0x7f;
1180 for (i
= 0; i
< numBytes
- 1; i
++)
1181 *pbEncoded
++ = outBytes
[i
] | 0x80;
1182 *pbEncoded
++ = outBytes
[i
];
1191 *pcbEncoded
= bytesNeeded
;
1195 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1196 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1199 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1202 switch (value
->dwValueType
)
1204 case CERT_RDN_NUMERIC_STRING
:
1205 tag
= ASN_NUMERICSTRING
;
1206 encodedLen
= value
->Value
.cbData
;
1208 case CERT_RDN_PRINTABLE_STRING
:
1209 tag
= ASN_PRINTABLESTRING
;
1210 encodedLen
= value
->Value
.cbData
;
1212 case CERT_RDN_IA5_STRING
:
1213 tag
= ASN_IA5STRING
;
1214 encodedLen
= value
->Value
.cbData
;
1216 case CERT_RDN_ANY_TYPE
:
1217 /* explicitly disallowed */
1218 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1221 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
1224 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1225 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1228 if (*pcbEncoded
< bytesNeeded
)
1230 SetLastError(ERROR_MORE_DATA
);
1236 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1237 pbEncoded
+= lenBytes
;
1238 switch (value
->dwValueType
)
1240 case CERT_RDN_NUMERIC_STRING
:
1241 case CERT_RDN_PRINTABLE_STRING
:
1242 case CERT_RDN_IA5_STRING
:
1243 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1247 *pcbEncoded
= bytesNeeded
;
1251 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1252 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1254 DWORD bytesNeeded
= 0, lenBytes
, size
;
1257 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1258 0, NULL
, NULL
, &size
);
1261 bytesNeeded
+= size
;
1262 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1263 * with dwValueType, so "cast" it to get its encoded size
1265 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1266 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1269 bytesNeeded
+= size
;
1270 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1271 bytesNeeded
+= 1 + lenBytes
;
1274 if (*pcbEncoded
< bytesNeeded
)
1276 SetLastError(ERROR_MORE_DATA
);
1281 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SEQUENCE
;
1282 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1284 pbEncoded
+= lenBytes
;
1285 size
= bytesNeeded
- 1 - lenBytes
;
1286 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1287 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1291 size
= bytesNeeded
- 1 - lenBytes
- size
;
1292 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1293 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1298 *pcbEncoded
= bytesNeeded
;
1304 static int BLOBComp(const void *l
, const void *r
)
1306 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1309 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1310 ret
= a
->cbData
- b
->cbData
;
1314 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1316 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1317 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1320 CRYPT_DER_BLOB
*blobs
= NULL
;
1324 DWORD bytesNeeded
= 0, lenBytes
, i
;
1329 blobs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1330 rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1334 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1336 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1337 NULL
, &blobs
[i
].cbData
);
1339 bytesNeeded
+= blobs
[i
].cbData
;
1343 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1344 bytesNeeded
+= 1 + lenBytes
;
1347 if (*pcbEncoded
< bytesNeeded
)
1349 SetLastError(ERROR_MORE_DATA
);
1354 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1356 blobs
[i
].pbData
= HeapAlloc(GetProcessHeap(), 0,
1358 if (!blobs
[i
].pbData
)
1361 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1362 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1367 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1369 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1370 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1372 pbEncoded
+= lenBytes
;
1373 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1375 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1376 pbEncoded
+= blobs
[i
].cbData
;
1381 *pcbEncoded
= bytesNeeded
;
1385 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1386 HeapFree(GetProcessHeap(), 0, blobs
[i
].pbData
);
1389 __EXCEPT(page_fault
)
1391 SetLastError(STATUS_ACCESS_VIOLATION
);
1395 HeapFree(GetProcessHeap(), 0, blobs
);
1399 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1400 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1401 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1407 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1408 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1410 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1412 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1414 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1417 bytesNeeded
+= size
;
1419 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1420 bytesNeeded
+= 1 + lenBytes
;
1424 *pcbEncoded
= bytesNeeded
;
1427 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1428 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1430 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1431 pbEncoded
= *(BYTE
**)pbEncoded
;
1432 *pbEncoded
++ = ASN_SEQUENCEOF
;
1433 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1435 pbEncoded
+= lenBytes
;
1436 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1439 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1440 &info
->rgRDN
[i
], pbEncoded
, &size
);
1444 bytesNeeded
-= size
;
1451 __EXCEPT(page_fault
)
1453 SetLastError(STATUS_ACCESS_VIOLATION
);
1460 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1461 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1462 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1464 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1473 else if (*pcbEncoded
< 3)
1476 SetLastError(ERROR_MORE_DATA
);
1482 *pbEncoded
++ = ASN_BOOL
;
1484 *pbEncoded
++ = val
? 0xff : 0;
1487 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1491 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1492 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1498 switch (entry
->dwAltNameChoice
)
1500 case CERT_ALT_NAME_RFC822_NAME
:
1501 case CERT_ALT_NAME_DNS_NAME
:
1502 case CERT_ALT_NAME_URL
:
1503 if (entry
->u
.pwszURL
)
1507 /* Not + 1: don't encode the NULL-terminator */
1508 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1509 for (i
= 0; ret
&& i
< dataLen
; i
++)
1511 if (entry
->u
.pwszURL
[i
] > 0x7f)
1513 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1522 case CERT_ALT_NAME_IP_ADDRESS
:
1523 dataLen
= entry
->u
.IPAddress
.cbData
;
1525 case CERT_ALT_NAME_REGISTERED_ID
:
1526 /* FIXME: encode OID */
1527 case CERT_ALT_NAME_OTHER_NAME
:
1528 case CERT_ALT_NAME_DIRECTORY_NAME
:
1529 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1532 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1537 DWORD bytesNeeded
, lenBytes
;
1539 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1540 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1542 *pcbEncoded
= bytesNeeded
;
1543 else if (*pcbEncoded
< bytesNeeded
)
1545 SetLastError(ERROR_MORE_DATA
);
1546 *pcbEncoded
= bytesNeeded
;
1551 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1552 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1553 pbEncoded
+= lenBytes
;
1554 switch (entry
->dwAltNameChoice
)
1556 case CERT_ALT_NAME_RFC822_NAME
:
1557 case CERT_ALT_NAME_DNS_NAME
:
1558 case CERT_ALT_NAME_URL
:
1562 for (i
= 0; i
< dataLen
; i
++)
1563 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1566 case CERT_ALT_NAME_IP_ADDRESS
:
1567 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1571 *pcbEncoded
= bytesNeeded
;
1577 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1578 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1579 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1585 const CERT_ALT_NAME_INFO
*info
=
1586 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1588 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1591 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1592 * can't encode an erroneous entry index if it's bigger than this.
1594 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1598 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1605 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1606 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1609 *pcbEncoded
= bytesNeeded
;
1614 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1615 pbEncoded
, pcbEncoded
, bytesNeeded
)))
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
++)
1624 DWORD len
= dataLen
;
1626 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1633 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1635 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1636 * the bad character, now set the index of the bad
1639 *pcbEncoded
|= (BYTE
)i
<<
1640 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
;
1647 __EXCEPT(page_fault
)
1649 SetLastError(STATUS_ACCESS_VIOLATION
);
1656 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1657 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1658 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1664 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1665 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1666 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1671 items
[cItem
].pvStructInfo
= &info
->fCA
;
1672 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1675 if (info
->fPathLenConstraint
)
1677 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1678 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1681 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1682 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1684 __EXCEPT(page_fault
)
1686 SetLastError(STATUS_ACCESS_VIOLATION
);
1693 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1694 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1695 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1701 const BLOBHEADER
*hdr
=
1702 (const BLOBHEADER
*)pvStructInfo
;
1704 if (hdr
->bType
!= PUBLICKEYBLOB
)
1706 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1711 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1712 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1713 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1714 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1715 struct AsnEncodeSequenceItem items
[] = {
1716 { &blob
, CRYPT_AsnEncodeInteger
, 0 },
1717 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1720 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1721 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1725 __EXCEPT(page_fault
)
1727 SetLastError(STATUS_ACCESS_VIOLATION
);
1734 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1735 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1736 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1742 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1743 DWORD bytesNeeded
, lenBytes
;
1745 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1746 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1748 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1749 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1752 *pcbEncoded
= bytesNeeded
;
1757 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1758 pcbEncoded
, bytesNeeded
)))
1760 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1761 pbEncoded
= *(BYTE
**)pbEncoded
;
1762 *pbEncoded
++ = ASN_OCTETSTRING
;
1763 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1764 pbEncoded
+= lenBytes
;
1766 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1770 __EXCEPT(page_fault
)
1772 SetLastError(STATUS_ACCESS_VIOLATION
);
1776 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1780 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1781 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1782 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1788 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1789 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1792 /* yep, MS allows cUnusedBits to be >= 8 */
1793 if (!blob
->cUnusedBits
)
1795 dataBytes
= blob
->cbData
;
1798 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1800 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1801 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1809 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1810 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1813 *pcbEncoded
= bytesNeeded
;
1818 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1819 pcbEncoded
, bytesNeeded
)))
1821 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1822 pbEncoded
= *(BYTE
**)pbEncoded
;
1823 *pbEncoded
++ = ASN_BITSTRING
;
1824 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1825 pbEncoded
+= lenBytes
;
1826 *pbEncoded
++ = unusedBits
;
1829 BYTE mask
= 0xff << unusedBits
;
1833 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1834 pbEncoded
+= dataBytes
- 1;
1836 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1841 __EXCEPT(page_fault
)
1843 SetLastError(STATUS_ACCESS_VIOLATION
);
1850 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1851 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1852 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1858 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1859 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1864 newBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, newBlob
.cbData
);
1869 for (i
= 0; i
< newBlob
.cbData
; i
++)
1870 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1876 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1877 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1878 HeapFree(GetProcessHeap(), 0, newBlob
.pbData
);
1880 __EXCEPT(page_fault
)
1882 SetLastError(STATUS_ACCESS_VIOLATION
);
1889 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1890 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1891 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1893 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1895 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1896 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1899 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1900 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1901 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1907 DWORD significantBytes
, lenBytes
;
1908 BYTE padByte
= 0, bytesNeeded
;
1910 const CRYPT_INTEGER_BLOB
*blob
=
1911 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1913 significantBytes
= blob
->cbData
;
1914 if (significantBytes
)
1916 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1918 /* negative, lop off leading (little-endian) 0xffs */
1919 for (; significantBytes
> 0 &&
1920 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1922 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1930 /* positive, lop off leading (little-endian) zeroes */
1931 for (; significantBytes
> 0 &&
1932 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1934 if (significantBytes
== 0)
1935 significantBytes
= 1;
1936 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1944 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1946 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1947 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1952 *pcbEncoded
= bytesNeeded
;
1957 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1958 pcbEncoded
, bytesNeeded
)))
1960 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1961 pbEncoded
= *(BYTE
**)pbEncoded
;
1962 *pbEncoded
++ = ASN_INTEGER
;
1965 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1966 pbEncoded
+= lenBytes
;
1967 *pbEncoded
++ = padByte
;
1971 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1972 pbEncoded
+= lenBytes
;
1974 for (; significantBytes
> 0; significantBytes
--)
1975 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1979 __EXCEPT(page_fault
)
1981 SetLastError(STATUS_ACCESS_VIOLATION
);
1988 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1989 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1990 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1996 DWORD significantBytes
, lenBytes
;
1999 const CRYPT_INTEGER_BLOB
*blob
=
2000 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2002 significantBytes
= blob
->cbData
;
2003 if (significantBytes
)
2005 /* positive, lop off leading (little-endian) zeroes */
2006 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2009 if (significantBytes
== 0)
2010 significantBytes
= 1;
2011 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2015 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2017 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2018 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2023 *pcbEncoded
= bytesNeeded
;
2028 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2029 pcbEncoded
, bytesNeeded
)))
2031 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2032 pbEncoded
= *(BYTE
**)pbEncoded
;
2033 *pbEncoded
++ = ASN_INTEGER
;
2036 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2037 pbEncoded
+= lenBytes
;
2042 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2043 pbEncoded
+= lenBytes
;
2045 for (; significantBytes
> 0; significantBytes
--)
2046 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2050 __EXCEPT(page_fault
)
2052 SetLastError(STATUS_ACCESS_VIOLATION
);
2059 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2060 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2061 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2063 CRYPT_INTEGER_BLOB blob
;
2066 /* Encode as an unsigned integer, then change the tag to enumerated */
2067 blob
.cbData
= sizeof(DWORD
);
2068 blob
.pbData
= (BYTE
*)pvStructInfo
;
2069 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2070 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2071 if (ret
&& pbEncoded
)
2073 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2074 pbEncoded
= *(BYTE
**)pbEncoded
;
2075 pbEncoded
[0] = ASN_ENUMERATED
;
2080 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2081 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2082 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2089 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2090 * temporary buffer because the output buffer is not NULL-terminated.
2093 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2097 *pcbEncoded
= bytesNeeded
;
2102 /* Sanity check the year, this is a two-digit year format */
2103 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2105 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2107 SetLastError(CRYPT_E_BAD_ENCODE
);
2112 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2113 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2115 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2116 pbEncoded
= *(BYTE
**)pbEncoded
;
2117 buf
[0] = ASN_UTCTIME
;
2118 buf
[1] = bytesNeeded
- 2;
2119 snprintf(buf
+ 2, sizeof(buf
) - 2,
2120 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2121 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2122 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2123 sysTime
.wMinute
, sysTime
.wSecond
);
2124 memcpy(pbEncoded
, buf
, bytesNeeded
);
2129 __EXCEPT(page_fault
)
2131 SetLastError(STATUS_ACCESS_VIOLATION
);
2138 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2139 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2140 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2147 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2148 * temporary buffer because the output buffer is not NULL-terminated.
2151 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2155 *pcbEncoded
= bytesNeeded
;
2160 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2163 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2164 pcbEncoded
, bytesNeeded
);
2167 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2168 pbEncoded
= *(BYTE
**)pbEncoded
;
2169 buf
[0] = ASN_GENERALTIME
;
2170 buf
[1] = bytesNeeded
- 2;
2171 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2172 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2173 sysTime
.wMinute
, sysTime
.wSecond
);
2174 memcpy(pbEncoded
, buf
, bytesNeeded
);
2178 __EXCEPT(page_fault
)
2180 SetLastError(STATUS_ACCESS_VIOLATION
);
2187 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2188 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2189 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2197 /* Check the year, if it's in the UTCTime range call that encode func */
2198 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2200 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2201 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2202 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2204 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2205 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2208 __EXCEPT(page_fault
)
2210 SetLastError(STATUS_ACCESS_VIOLATION
);
2217 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2218 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2219 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2225 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2226 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2227 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2229 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2230 dataLen
+= seq
->rgValue
[i
].cbData
;
2231 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2232 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2235 *pcbEncoded
= bytesNeeded
;
2240 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2241 pcbEncoded
, bytesNeeded
)))
2243 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2244 pbEncoded
= *(BYTE
**)pbEncoded
;
2245 *pbEncoded
++ = ASN_SEQUENCEOF
;
2246 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2247 pbEncoded
+= lenBytes
;
2248 for (i
= 0; i
< seq
->cValue
; i
++)
2250 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2251 seq
->rgValue
[i
].cbData
);
2252 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2257 __EXCEPT(page_fault
)
2259 SetLastError(STATUS_ACCESS_VIOLATION
);
2266 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2267 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2268 void *pvEncoded
, DWORD
*pcbEncoded
)
2272 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2274 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2275 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2276 pvEncoded
, pcbEncoded
);
2278 if (!pvEncoded
&& !pcbEncoded
)
2280 SetLastError(ERROR_INVALID_PARAMETER
);
2283 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2284 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2286 SetLastError(ERROR_FILE_NOT_FOUND
);
2290 SetLastError(NOERROR
);
2291 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2292 *(BYTE
**)pvEncoded
= NULL
;
2293 if (!HIWORD(lpszStructType
))
2295 switch (LOWORD(lpszStructType
))
2297 case (WORD
)X509_CERT
:
2298 encodeFunc
= CRYPT_AsnEncodeCert
;
2300 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2301 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2303 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2304 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2306 case (WORD
)X509_EXTENSIONS
:
2307 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2309 case (WORD
)X509_NAME
:
2310 encodeFunc
= CRYPT_AsnEncodeName
;
2312 case (WORD
)X509_PUBLIC_KEY_INFO
:
2313 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2315 case (WORD
)X509_ALTERNATE_NAME
:
2316 encodeFunc
= CRYPT_AsnEncodeAltName
;
2318 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2319 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2321 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2322 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2324 case (WORD
)X509_OCTET_STRING
:
2325 encodeFunc
= CRYPT_AsnEncodeOctets
;
2327 case (WORD
)X509_BITS
:
2328 case (WORD
)X509_KEY_USAGE
:
2329 encodeFunc
= CRYPT_AsnEncodeBits
;
2331 case (WORD
)X509_INTEGER
:
2332 encodeFunc
= CRYPT_AsnEncodeInt
;
2334 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2335 encodeFunc
= CRYPT_AsnEncodeInteger
;
2337 case (WORD
)X509_MULTI_BYTE_UINT
:
2338 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2340 case (WORD
)X509_ENUMERATED
:
2341 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2343 case (WORD
)X509_CHOICE_OF_TIME
:
2344 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2346 case (WORD
)X509_SEQUENCE_OF_ANY
:
2347 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2349 case (WORD
)PKCS_UTC_TIME
:
2350 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2353 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2356 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2357 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2358 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2359 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2360 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2361 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2362 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2363 encodeFunc
= CRYPT_AsnEncodeBits
;
2364 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2365 encodeFunc
= CRYPT_AsnEncodeOctets
;
2366 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2367 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2368 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2369 encodeFunc
= CRYPT_AsnEncodeAltName
;
2370 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2371 encodeFunc
= CRYPT_AsnEncodeAltName
;
2372 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2373 encodeFunc
= CRYPT_AsnEncodeAltName
;
2374 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2375 encodeFunc
= CRYPT_AsnEncodeAltName
;
2376 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2377 encodeFunc
= CRYPT_AsnEncodeAltName
;
2379 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2380 debugstr_a(lpszStructType
));
2382 encodeFunc
= (CryptEncodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2383 lpszStructType
, "CryptEncodeObjectEx", &lib
);
2385 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2386 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2388 SetLastError(ERROR_FILE_NOT_FOUND
);
2394 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2395 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2396 DWORD
*pcbStructInfo
)
2400 CryptDecodeObjectFunc pCryptDecodeObject
;
2402 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2403 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2404 pvStructInfo
, pcbStructInfo
);
2406 if (!pvStructInfo
&& !pcbStructInfo
)
2408 SetLastError(ERROR_INVALID_PARAMETER
);
2412 /* Try registered DLL first.. */
2413 pCryptDecodeObject
=
2414 (CryptDecodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2415 lpszStructType
, "CryptDecodeObject", &lib
);
2416 if (pCryptDecodeObject
)
2418 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2419 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2424 /* If not, use CryptDecodeObjectEx */
2425 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2426 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2431 /* Gets the number of length bytes from the given (leading) length byte */
2432 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2434 /* Helper function to get the encoded length of the data starting at pbEncoded,
2435 * where pbEncoded[0] is the tag. If the data are too short to contain a
2436 * length or if the length is too large for cbEncoded, sets an appropriate
2437 * error code and returns FALSE.
2439 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2446 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2449 else if (pbEncoded
[1] <= 0x7f)
2451 if (pbEncoded
[1] + 1 > cbEncoded
)
2453 SetLastError(CRYPT_E_ASN1_EOD
);
2458 *len
= pbEncoded
[1];
2464 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2466 if (lenLen
> sizeof(DWORD
) + 1)
2468 SetLastError(CRYPT_E_ASN1_LARGE
);
2471 else if (lenLen
+ 2 > cbEncoded
)
2473 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2484 out
|= *pbEncoded
++;
2486 if (out
+ lenLen
+ 1 > cbEncoded
)
2488 SetLastError(CRYPT_E_ASN1_EOD
);
2501 /* Helper function to check *pcbStructInfo, set it to the required size, and
2502 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2503 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2504 * pointer to the newly allocated memory.
2506 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2507 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2512 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2514 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2515 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2517 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2518 if (!*(BYTE
**)pvStructInfo
)
2521 *pcbStructInfo
= bytesNeeded
;
2523 else if (*pcbStructInfo
< bytesNeeded
)
2525 *pcbStructInfo
= bytesNeeded
;
2526 SetLastError(ERROR_MORE_DATA
);
2532 /* A few of the members need explanation:
2534 * A sequence is decoded into a struct. The offset member is the
2535 * offset of this item within that struct.
2537 * The decoder function to use. If this is NULL, then the member isn't
2538 * decoded, but minSize space is reserved for it.
2540 * The minimum amount of space occupied after decoding. You must set this.
2541 * hasPointer, pointerOffset, minSize:
2542 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2543 * the offset within the (outer) struct of the data pointer (or to the
2544 * first data pointer, if more than one exist).
2546 * Used by CRYPT_AsnDecodeSequence, not for your use.
2548 struct AsnDecodeSequenceItem
2551 CryptDecodeObjectExFunc decodeFunc
;
2555 DWORD pointerOffset
;
2559 /* This decodes an arbitrary sequence into a contiguous block of memory
2560 * (basically, a struct.) Each element being decoded is described by a struct
2561 * AsnDecodeSequenceItem, see above.
2562 * startingPointer is an optional pointer to the first place where dynamic
2563 * data will be stored. If you know the starting offset, you may pass it
2564 * here. Otherwise, pass NULL, and one will be inferred from the items.
2565 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2566 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2567 * FIXME: use to decode more sequences.
2569 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2570 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2571 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2572 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2576 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, pbEncoded
,
2577 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2579 if (pbEncoded
[0] == ASN_SEQUENCE
)
2583 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2585 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2586 DWORD i
, bytesNeeded
= 0, minSize
= 0;
2589 ptr
= pbEncoded
+ 1 + lenBytes
;
2590 for (i
= 0; ret
&& i
< cItem
; i
++)
2594 minSize
+= items
[i
].minSize
;
2595 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2597 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2600 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2602 if (items
[i
].decodeFunc
)
2604 ret
= items
[i
].decodeFunc(dwCertEncodingType
, NULL
,
2605 ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2606 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2610 /* Account for alignment padding */
2611 bytesNeeded
+= items
[i
].size
;
2612 if (items
[i
].size
% sizeof(DWORD
))
2613 bytesNeeded
+= sizeof(DWORD
) -
2614 items
[i
].size
% sizeof(DWORD
);
2615 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2617 else if (items
[i
].optional
&&
2618 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2620 bytesNeeded
+= items
[i
].minSize
;
2621 SetLastError(NOERROR
);
2626 bytesNeeded
+= items
[i
].minSize
;
2629 else if (items
[i
].optional
)
2630 bytesNeeded
+= items
[i
].minSize
;
2633 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2640 *pcbStructInfo
= bytesNeeded
;
2641 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2642 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2646 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2647 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2648 if (startingPointer
)
2649 nextData
= (BYTE
*)startingPointer
;
2651 nextData
= (BYTE
*)pvStructInfo
+ minSize
;
2652 memset(pvStructInfo
, 0, minSize
);
2653 ptr
= pbEncoded
+ 1 + lenBytes
;
2654 for (i
= 0; ret
&& i
< cItem
; i
++)
2656 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2659 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2661 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2663 if (items
[i
].hasPointer
)
2664 *(BYTE
**)((BYTE
*)pvStructInfo
+
2665 items
[i
].pointerOffset
) = nextData
;
2666 if (items
[i
].decodeFunc
)
2667 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2668 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2669 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2670 (BYTE
*)pvStructInfo
+ items
[i
].offset
,
2673 items
[i
].size
= items
[i
].minSize
;
2676 if (items
[i
].hasPointer
&&
2677 items
[i
].size
> items
[i
].minSize
)
2679 nextData
+= items
[i
].size
-
2681 /* align nextData to DWORD boundaries */
2682 if (items
[i
].size
% sizeof(DWORD
))
2683 nextData
+= sizeof(DWORD
) -
2684 items
[i
].size
% sizeof(DWORD
);
2686 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2688 else if (items
[i
].optional
&&
2689 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2691 SetLastError(NOERROR
);
2695 else if (!items
[i
].optional
)
2697 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2707 SetLastError(CRYPT_E_ASN1_BADTAG
);
2710 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2714 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2715 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2716 * to CRYPT_E_ASN1_CORRUPT.
2717 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2720 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2721 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2722 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2727 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2729 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2730 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2732 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2733 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2736 *pcbStructInfo
= bytesNeeded
;
2737 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2738 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2740 CRYPT_DER_BLOB
*blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
2742 blob
->cbData
= 1 + lenBytes
+ dataLen
;
2745 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2746 blob
->pbData
= (BYTE
*)pbEncoded
;
2749 assert(blob
->pbData
);
2750 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
2755 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2763 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2764 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
2765 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2766 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2770 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
2771 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
2772 if (ret
&& pvStructInfo
)
2774 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2778 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2780 temp
= blob
->pbData
[i
];
2781 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2782 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2788 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
2789 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2790 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2794 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2795 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2799 struct AsnDecodeSequenceItem items
[] = {
2800 { offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
2801 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2802 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
2803 { offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
),
2804 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2805 FALSE
, TRUE
, offsetof(CERT_SIGNED_CONTENT_INFO
,
2806 SignatureAlgorithm
.Parameters
.pbData
), 0 },
2807 { offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
2808 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2809 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
2812 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
2813 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
2814 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2815 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2816 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2818 __EXCEPT(page_fault
)
2820 SetLastError(STATUS_ACCESS_VIOLATION
);
2827 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
2828 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2829 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2833 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
))
2837 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2839 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2841 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2842 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
2843 pvStructInfo
, pcbStructInfo
);
2848 SetLastError(CRYPT_E_ASN1_BADTAG
);
2854 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
2855 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2856 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2860 struct AsnDecodeSequenceItem items
[] = {
2861 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
2862 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2863 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
2864 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2867 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2868 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2869 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2873 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
2874 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2875 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2879 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2880 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2884 struct AsnDecodeSequenceItem items
[] = {
2885 { offsetof(CERT_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
2886 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
2887 { offsetof(CERT_INFO
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2888 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2889 SerialNumber
.pbData
), 0 },
2890 { offsetof(CERT_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
2891 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2892 SignatureAlgorithm
.Parameters
.pbData
), 0 },
2893 { offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
2894 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2896 { offsetof(CERT_INFO
, NotBefore
), CRYPT_AsnDecodeValidity
,
2897 sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
, FALSE
, 0 },
2898 { offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
2899 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2901 { offsetof(CERT_INFO
, SubjectPublicKeyInfo
), CRYPT_AsnDecodePubKeyInfo
,
2902 sizeof(CERT_PUBLIC_KEY_INFO
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2903 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
2904 { offsetof(CERT_INFO
, IssuerUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2905 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2906 IssuerUniqueId
.pbData
), 0 },
2907 { offsetof(CERT_INFO
, SubjectUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2908 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2909 SubjectUniqueId
.pbData
), 0 },
2910 { offsetof(CERT_INFO
, cExtension
), CRYPT_AsnDecodeExtensionsInternal
,
2911 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2915 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2916 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2917 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2919 __EXCEPT(page_fault
)
2921 SetLastError(STATUS_ACCESS_VIOLATION
);
2928 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2929 DWORD dwFlags
, PCRL_ENTRY entry
, DWORD
*pcbEntry
)
2932 struct AsnDecodeSequenceItem items
[] = {
2933 { offsetof(CRL_ENTRY
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2934 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CRL_ENTRY
,
2935 SerialNumber
.pbData
), 0 },
2936 { offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
2937 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2938 { offsetof(CRL_ENTRY
, cExtension
), CRYPT_AsnDecodeExtensionsInternal
,
2939 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CRL_ENTRY
,
2943 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
2946 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
2947 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2948 NULL
, entry
, pcbEntry
, entry
? entry
->SerialNumber
.pbData
: NULL
);
2949 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
2953 typedef struct _WINE_CRL_ENTRIES
{
2955 PCRL_ENTRY rgCRLEntry
;
2956 } WINE_CRL_ENTRIES
, *PWINE_CRL_ENTRIES
;
2958 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
2959 * been set prior to calling.
2961 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
2962 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2963 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2967 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2968 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2970 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
2972 DWORD dataLen
, bytesNeeded
;
2974 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2976 DWORD cCRLEntry
= 0;
2977 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2979 bytesNeeded
= sizeof(WINE_CRL_ENTRIES
);
2985 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2986 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
2989 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
2990 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
2996 bytesNeeded
+= size
;
2997 ret
= CRYPT_GetLen(ptr
,
2998 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3000 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3007 *pcbStructInfo
= bytesNeeded
;
3008 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3009 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3014 PWINE_CRL_ENTRIES entries
;
3016 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3017 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3018 *pcbStructInfo
= bytesNeeded
;
3019 entries
= (PWINE_CRL_ENTRIES
)pvStructInfo
;
3020 entries
->cCRLEntry
= cCRLEntry
;
3021 assert(entries
->rgCRLEntry
);
3022 nextData
= (BYTE
*)entries
->rgCRLEntry
+
3023 entries
->cCRLEntry
* sizeof(CRL_ENTRY
);
3024 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3025 i
< cCRLEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
3028 entries
->rgCRLEntry
[i
].SerialNumber
.pbData
= nextData
;
3030 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3031 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3032 &entries
->rgCRLEntry
[i
], &size
);
3037 bytesNeeded
-= size
;
3038 /* Increment nextData by the difference of the
3039 * minimum size and the actual size.
3041 if (size
> sizeof(CRL_ENTRY
))
3042 nextData
+= size
- sizeof(CRL_ENTRY
);
3043 ret
= CRYPT_GetLen(ptr
,
3044 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3046 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3055 SetLastError(CRYPT_E_ASN1_BADTAG
);
3058 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3062 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
3063 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3064 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3068 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3069 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3073 struct AsnDecodeSequenceItem items
[] = {
3074 { offsetof(CRL_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
3075 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3076 { offsetof(CRL_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
3077 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3078 SignatureAlgorithm
.Parameters
.pbData
), 0 },
3079 { offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3080 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3082 { offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3083 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3084 { offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3085 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
3086 { offsetof(CRL_INFO
, cCRLEntry
), CRYPT_AsnDecodeCRLEntries
,
3087 sizeof(WINE_CRL_ENTRIES
), TRUE
, TRUE
, offsetof(CRL_INFO
,
3089 /* Note that the extensions are ignored by MS, so I'll ignore them too
3091 { offsetof(CRL_INFO
, cExtension
), NULL
,
3092 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
3095 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3096 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3097 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3099 __EXCEPT(page_fault
)
3101 SetLastError(STATUS_ACCESS_VIOLATION
);
3106 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3110 /* Warning: assumes ext->Value.pbData is set ahead of time! */
3111 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3112 DWORD dwFlags
, CERT_EXTENSION
*ext
, DWORD
*pcbExt
)
3116 if (pbEncoded
[0] == ASN_SEQUENCE
)
3118 DWORD dataLen
, bytesNeeded
;
3120 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3122 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), oidLenBytes
= 0;
3124 bytesNeeded
= sizeof(CERT_EXTENSION
);
3127 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
3128 DWORD encodedOidLen
, oidLen
;
3130 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
3132 oidLenBytes
= GET_LEN_BYTES(ptr
[1]);
3133 ret
= CRYPT_AsnDecodeOid(ptr
, cbEncoded
- (ptr
- pbEncoded
),
3134 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &oidLen
);
3137 bytesNeeded
+= oidLen
;
3138 ptr
+= 1 + encodedOidLen
+ oidLenBytes
;
3139 if (*ptr
== ASN_BOOL
)
3141 ret
= CRYPT_AsnDecodeOctets(X509_ASN_ENCODING
,
3142 X509_OCTET_STRING
, ptr
, cbEncoded
- (ptr
- pbEncoded
),
3143 0, NULL
, NULL
, &dataLen
);
3144 bytesNeeded
+= dataLen
;
3148 *pcbExt
= bytesNeeded
;
3149 else if (*pcbExt
< bytesNeeded
)
3151 SetLastError(ERROR_MORE_DATA
);
3156 ptr
= pbEncoded
+ 2 + lenBytes
+ encodedOidLen
+
3158 if (*ptr
== ASN_BOOL
)
3160 DWORD size
= sizeof(BOOL
);
3162 CRYPT_AsnDecodeBool(X509_ASN_ENCODING
, NULL
,
3163 ptr
, cbEncoded
- (ptr
- pbEncoded
),
3164 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
3165 &ext
->fCritical
, &size
);
3169 ext
->fCritical
= FALSE
;
3170 ret
= CRYPT_AsnDecodeOctets(X509_ASN_ENCODING
,
3171 X509_OCTET_STRING
, ptr
,
3172 cbEncoded
- (ptr
- pbEncoded
),
3173 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
3174 &ext
->Value
, &dataLen
);
3177 ext
->pszObjId
= (LPSTR
)ext
->Value
.pbData
+
3179 ptr
= pbEncoded
+ 1 + lenBytes
;
3180 ret
= CRYPT_AsnDecodeOid(ptr
,
3181 cbEncoded
- (ptr
- pbEncoded
),
3182 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
3183 ext
->pszObjId
, &oidLen
);
3191 SetLastError(CRYPT_E_ASN1_EOD
);
3198 SetLastError(CRYPT_E_ASN1_BADTAG
);
3204 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
3205 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3206 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3210 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3212 DWORD dataLen
, bytesNeeded
;
3214 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3216 DWORD cExtension
= 0;
3217 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3219 bytesNeeded
= sizeof(CERT_EXTENSIONS
);
3225 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3226 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3228 ret
= CRYPT_AsnDecodeExtension(ptr
,
3229 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3235 bytesNeeded
+= size
;
3236 ret
= CRYPT_GetLen(ptr
,
3237 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3239 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3246 *pcbStructInfo
= bytesNeeded
;
3247 else if (*pcbStructInfo
< bytesNeeded
)
3249 SetLastError(ERROR_MORE_DATA
);
3250 *pcbStructInfo
= bytesNeeded
;
3258 CERT_EXTENSIONS
*exts
;
3260 *pcbStructInfo
= bytesNeeded
;
3261 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3262 exts
->cExtension
= cExtension
;
3263 assert(exts
->rgExtension
);
3264 nextData
= (BYTE
*)exts
->rgExtension
+
3265 exts
->cExtension
* sizeof(CERT_EXTENSION
);
3266 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3267 i
< cExtension
&& ptr
- pbEncoded
- 1 - lenBytes
<
3270 exts
->rgExtension
[i
].Value
.pbData
= nextData
;
3272 ret
= CRYPT_AsnDecodeExtension(ptr
,
3273 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3274 &exts
->rgExtension
[i
], &size
);
3279 bytesNeeded
-= size
;
3280 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3281 * data may not have been copied.
3283 if (exts
->rgExtension
[i
].Value
.pbData
==
3286 exts
->rgExtension
[i
].Value
.cbData
;
3287 /* Ugly: the OID, if copied, is stored in
3288 * memory after the value, so increment by its
3289 * string length if it's set and points here.
3291 if ((const BYTE
*)exts
->rgExtension
[i
].pszObjId
3294 exts
->rgExtension
[i
].pszObjId
) + 1;
3295 ret
= CRYPT_GetLen(ptr
,
3296 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3298 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3307 SetLastError(CRYPT_E_ASN1_BADTAG
);
3313 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3314 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3315 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3321 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3322 lpszStructType
, pbEncoded
, cbEncoded
,
3323 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3324 if (ret
&& pvStructInfo
)
3326 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3327 pcbStructInfo
, *pcbStructInfo
);
3330 CERT_EXTENSIONS
*exts
;
3332 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3333 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3334 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3335 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3336 sizeof(CERT_EXTENSIONS
));
3337 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3338 lpszStructType
, pbEncoded
, cbEncoded
,
3339 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3344 __EXCEPT(page_fault
)
3346 SetLastError(STATUS_ACCESS_VIOLATION
);
3353 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3354 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3355 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
)
3361 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3365 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3367 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3372 /* The largest possible string for the first two components
3373 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3378 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3379 pbEncoded
[1 + lenBytes
] / 40,
3380 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3382 bytesNeeded
= strlen(firstTwo
) + 1;
3383 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3384 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3386 /* large enough for ".4000000" */
3390 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3397 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3400 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3407 snprintf(str
, sizeof(str
), ".%d", val
);
3408 bytesNeeded
+= strlen(str
);
3412 *pcbObjId
= bytesNeeded
;
3413 else if (*pcbObjId
< bytesNeeded
)
3415 *pcbObjId
= bytesNeeded
;
3416 SetLastError(ERROR_MORE_DATA
);
3421 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3422 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3424 pszObjId
+= strlen(pszObjId
);
3425 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3426 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3430 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3439 sprintf(pszObjId
, ".%d", val
);
3440 pszObjId
+= strlen(pszObjId
);
3446 *pcbObjId
= bytesNeeded
;
3451 SetLastError(CRYPT_E_ASN1_BADTAG
);
3455 __EXCEPT(page_fault
)
3457 SetLastError(STATUS_ACCESS_VIOLATION
);
3464 /* Warning: this assumes the address of value->Value.pbData is already set, in
3465 * order to avoid overwriting memory. (In some cases, it may change it, if it
3466 * doesn't copy anything to memory.) Be sure to set it correctly!
3468 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(const BYTE
*pbEncoded
,
3469 DWORD cbEncoded
, DWORD dwFlags
, CERT_NAME_VALUE
*value
, DWORD
*pcbValue
)
3477 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3479 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3481 switch (pbEncoded
[0])
3483 case ASN_NUMERICSTRING
:
3484 case ASN_PRINTABLESTRING
:
3488 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3489 SetLastError(OSS_UNIMPLEMENTED
);
3494 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3496 switch (pbEncoded
[0])
3498 case ASN_NUMERICSTRING
:
3499 case ASN_PRINTABLESTRING
:
3501 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3502 bytesNeeded
+= dataLen
;
3506 *pcbValue
= bytesNeeded
;
3507 else if (*pcbValue
< bytesNeeded
)
3509 *pcbValue
= bytesNeeded
;
3510 SetLastError(ERROR_MORE_DATA
);
3515 *pcbValue
= bytesNeeded
;
3516 switch (pbEncoded
[0])
3518 case ASN_NUMERICSTRING
:
3519 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3521 case ASN_PRINTABLESTRING
:
3522 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3525 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3530 switch (pbEncoded
[0])
3532 case ASN_NUMERICSTRING
:
3533 case ASN_PRINTABLESTRING
:
3535 value
->Value
.cbData
= dataLen
;
3536 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3537 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3541 assert(value
->Value
.pbData
);
3542 memcpy(value
->Value
.pbData
,
3543 pbEncoded
+ 1 + lenBytes
, dataLen
);
3550 value
->Value
.cbData
= 0;
3551 value
->Value
.pbData
= NULL
;
3557 __EXCEPT(page_fault
)
3559 SetLastError(STATUS_ACCESS_VIOLATION
);
3566 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
,
3567 DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN_ATTR
*attr
, DWORD
*pcbAttr
)
3573 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
3575 DWORD bytesNeeded
, dataLen
, size
;
3578 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3580 /* The data length must be at least 4, two for the tag and
3581 * length for the OID, and two for the string (assuming both
3582 * have short-form lengths.)
3586 SetLastError(CRYPT_E_ASN1_EOD
);
3591 bytesNeeded
= sizeof(CERT_RDN_ATTR
);
3592 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3593 ret
= CRYPT_AsnDecodeOid(pbEncoded
+ 1 + lenBytes
,
3594 cbEncoded
- 1 - lenBytes
, dwFlags
, NULL
, &size
);
3597 /* ugly: need to know the size of the next element of
3598 * the sequence, so get it directly
3600 DWORD objIdOfset
= 1 + lenBytes
, objIdLen
,
3601 nameValueOffset
= 0;
3603 ret
= CRYPT_GetLen(pbEncoded
+ objIdOfset
,
3604 cbEncoded
- objIdOfset
, &objIdLen
);
3605 bytesNeeded
+= size
;
3606 /* hack: like encoding, this takes advantage of the
3607 * fact that the rest of the structure is identical to
3608 * a CERT_NAME_VALUE.
3612 nameValueOffset
= objIdOfset
+ objIdLen
+ 1 +
3613 GET_LEN_BYTES(pbEncoded
[objIdOfset
]);
3614 ret
= CRYPT_AsnDecodeNameValue(
3615 pbEncoded
+ nameValueOffset
,
3616 cbEncoded
- nameValueOffset
, dwFlags
, NULL
, &size
);
3620 bytesNeeded
+= size
;
3622 *pcbAttr
= bytesNeeded
;
3623 else if (*pcbAttr
< bytesNeeded
)
3625 *pcbAttr
= bytesNeeded
;
3626 SetLastError(ERROR_MORE_DATA
);
3631 BYTE
*originalData
= attr
->Value
.pbData
;
3633 *pcbAttr
= bytesNeeded
;
3634 /* strange: decode the value first, because it
3635 * has a counted size, and we can store the OID
3636 * after it. Keep track of the original data
3637 * pointer, we'll need to know whether it was
3641 ret
= CRYPT_AsnDecodeNameValue(
3642 pbEncoded
+ nameValueOffset
,
3643 cbEncoded
- nameValueOffset
, dwFlags
,
3644 (CERT_NAME_VALUE
*)&attr
->dwValueType
, &size
);
3649 /* if the data were copied to the
3650 * original location, the OID goes
3651 * after. Otherwise it goes in the
3652 * spot originally reserved for the
3655 if (attr
->Value
.pbData
== originalData
)
3657 (LPSTR
)(attr
->Value
.pbData
+
3658 attr
->Value
.cbData
);
3660 attr
->pszObjId
= (LPSTR
)originalData
;
3661 size
= bytesNeeded
- size
;
3662 ret
= CRYPT_AsnDecodeOid(
3663 pbEncoded
+ objIdOfset
,
3664 cbEncoded
- objIdOfset
,
3665 dwFlags
, attr
->pszObjId
, &size
);
3668 attr
->pszObjId
= NULL
;
3678 SetLastError(CRYPT_E_ASN1_BADTAG
);
3682 __EXCEPT(page_fault
)
3684 SetLastError(STATUS_ACCESS_VIOLATION
);
3691 static BOOL WINAPI
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3692 DWORD dwFlags
, CERT_RDN
*rdn
, DWORD
*pcbRdn
)
3698 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SETOF
))
3702 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3704 DWORD bytesNeeded
, cRDNAttr
= 0;
3705 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3707 bytesNeeded
= sizeof(CERT_RDN
);
3713 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3714 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3716 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3717 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3723 bytesNeeded
+= size
;
3724 ret
= CRYPT_GetLen(ptr
,
3725 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3727 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3734 *pcbRdn
= bytesNeeded
;
3735 else if (*pcbRdn
< bytesNeeded
)
3737 *pcbRdn
= bytesNeeded
;
3738 SetLastError(ERROR_MORE_DATA
);
3747 *pcbRdn
= bytesNeeded
;
3748 rdn
->cRDNAttr
= cRDNAttr
;
3749 rdn
->rgRDNAttr
= (CERT_RDN_ATTR
*)((BYTE
*)rdn
+
3751 nextData
= (BYTE
*)rdn
->rgRDNAttr
+
3752 rdn
->cRDNAttr
* sizeof(CERT_RDN_ATTR
);
3753 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3754 i
< cRDNAttr
&& ptr
- pbEncoded
- 1 - lenBytes
<
3757 rdn
->rgRDNAttr
[i
].Value
.pbData
= nextData
;
3759 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3760 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3761 &rdn
->rgRDNAttr
[i
], &size
);
3766 bytesNeeded
-= size
;
3767 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3768 * data may not have been copied.
3770 if (rdn
->rgRDNAttr
[i
].Value
.pbData
== nextData
)
3772 rdn
->rgRDNAttr
[i
].Value
.cbData
;
3773 /* Ugly: the OID, if copied, is stored in
3774 * memory after the value, so increment by its
3775 * string length if it's set and points here.
3777 if ((const BYTE
*)rdn
->rgRDNAttr
[i
].pszObjId
3780 rdn
->rgRDNAttr
[i
].pszObjId
) + 1;
3781 ret
= CRYPT_GetLen(ptr
,
3782 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3784 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3793 SetLastError(CRYPT_E_ASN1_BADTAG
);
3797 __EXCEPT(page_fault
)
3799 SetLastError(STATUS_ACCESS_VIOLATION
);
3806 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3807 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3808 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3814 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCEOF
))
3818 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3820 DWORD bytesNeeded
, cRDN
= 0;
3821 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3823 bytesNeeded
= sizeof(CERT_NAME_INFO
);
3828 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3829 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3833 ret
= CRYPT_AsnDecodeRdn(ptr
,
3834 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3840 bytesNeeded
+= size
;
3841 ret
= CRYPT_GetLen(ptr
,
3842 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3844 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3851 *pcbStructInfo
= bytesNeeded
;
3852 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3853 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3855 CERT_NAME_INFO
*info
;
3857 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3858 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3859 info
= (CERT_NAME_INFO
*)pvStructInfo
;
3861 if (info
->cRDN
== 0)
3869 info
->rgRDN
= (CERT_RDN
*)((BYTE
*)pvStructInfo
+
3870 sizeof(CERT_NAME_INFO
));
3871 nextData
= (BYTE
*)info
->rgRDN
+
3872 info
->cRDN
* sizeof(CERT_RDN
);
3873 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3874 i
< cRDN
&& ptr
- pbEncoded
- 1 - lenBytes
<
3877 info
->rgRDN
[i
].rgRDNAttr
=
3878 (CERT_RDN_ATTR
*)nextData
;
3880 ret
= CRYPT_AsnDecodeRdn(ptr
,
3881 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3882 &info
->rgRDN
[i
], &size
);
3888 bytesNeeded
-= size
;
3889 ret
= CRYPT_GetLen(ptr
,
3890 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3892 ptr
+= nextLen
+ 1 +
3893 GET_LEN_BYTES(ptr
[1]);
3903 SetLastError(CRYPT_E_ASN1_BADTAG
);
3907 __EXCEPT(page_fault
)
3909 SetLastError(STATUS_ACCESS_VIOLATION
);
3916 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3917 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3918 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3920 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3921 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3924 if (pbEncoded
[0] == ASN_SEQUENCE
)
3926 DWORD dataLen
, bytesNeeded
;
3928 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3930 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3932 bytesNeeded
= sizeof(CRYPT_ALGORITHM_IDENTIFIER
);
3935 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
3937 DWORD encodedOidLen
, oidLen
;
3939 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
3941 oidLenBytes
= GET_LEN_BYTES(ptr
[1]);
3942 ret
= CRYPT_AsnDecodeOid(ptr
, cbEncoded
- (ptr
- pbEncoded
),
3943 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &oidLen
);
3946 bytesNeeded
+= oidLen
;
3947 ptr
+= 1 + encodedOidLen
+ oidLenBytes
;
3948 /* The remaining bytes are just copied as-is, no decoding
3951 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3952 bytesNeeded
+= cbEncoded
- (ptr
- pbEncoded
);
3954 *pcbStructInfo
= bytesNeeded
;
3955 else if (*pcbStructInfo
< bytesNeeded
)
3957 SetLastError(ERROR_MORE_DATA
);
3962 /* Get and sanity-check parameter length first */
3963 if (dataLen
- 1 - oidLenBytes
- encodedOidLen
!= 0)
3967 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
-
3968 (ptr
- pbEncoded
), ¶msLen
)))
3970 BYTE paramsLenBytes
= GET_LEN_BYTES(ptr
[1]);
3972 if (paramsLen
!= dataLen
- encodedOidLen
- 1 -
3973 oidLenBytes
- 1 - paramsLenBytes
)
3975 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3982 *pcbStructInfo
= bytesNeeded
;
3983 algo
->Parameters
.cbData
= dataLen
- 1 -
3984 oidLenBytes
- encodedOidLen
;
3985 if (algo
->Parameters
.cbData
)
3987 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3989 memcpy(algo
->Parameters
.pbData
, ptr
,
3990 algo
->Parameters
.cbData
);
3991 algo
->pszObjId
= (LPSTR
)algo
->Parameters
.pbData
+
3992 algo
->Parameters
.cbData
;
3996 algo
->Parameters
.pbData
= (BYTE
*)ptr
;
3997 algo
->pszObjId
= (LPSTR
)algo
->Parameters
.pbData
;
4001 algo
->pszObjId
= (LPSTR
)algo
->Parameters
.pbData
;
4002 ptr
= pbEncoded
+ 1 + lenBytes
;
4003 ret
= CRYPT_AsnDecodeOid(ptr
,
4004 cbEncoded
- (ptr
- pbEncoded
),
4005 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
4006 algo
->pszObjId
, &oidLen
);
4013 SetLastError(CRYPT_E_ASN1_EOD
);
4020 SetLastError(CRYPT_E_ASN1_BADTAG
);
4026 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
4027 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4028 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4034 struct AsnDecodeSequenceItem items
[] = {
4035 { offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
4036 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
4037 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
4038 Algorithm
.Parameters
.pbData
) },
4039 { offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
4040 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
4041 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
4044 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4045 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4046 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4048 __EXCEPT(page_fault
)
4050 SetLastError(STATUS_ACCESS_VIOLATION
);
4057 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
4058 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4059 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4065 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4068 if (pbEncoded
[0] != ASN_BOOL
)
4070 SetLastError(CRYPT_E_ASN1_BADTAG
);
4073 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
4075 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4078 if (pbEncoded
[1] > 1)
4080 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4085 *pcbStructInfo
= sizeof(BOOL
);
4088 else if (*pcbStructInfo
< sizeof(BOOL
))
4090 *pcbStructInfo
= sizeof(BOOL
);
4091 SetLastError(ERROR_MORE_DATA
);
4096 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
4102 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4103 DWORD dwFlags
, CERT_ALT_NAME_ENTRY
*entry
, DWORD
*pcbEntry
)
4105 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
4110 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4113 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
4115 SetLastError(CRYPT_E_ASN1_BADTAG
);
4118 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4119 if (1 + lenBytes
> cbEncoded
)
4121 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4124 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4126 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4128 case 1: /* rfc822Name */
4129 case 2: /* dNSName */
4130 case 6: /* uniformResourceIdentifier */
4131 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
4133 case 7: /* iPAddress */
4134 bytesNeeded
+= dataLen
;
4136 case 8: /* registeredID */
4137 /* FIXME: decode as OID */
4138 case 0: /* otherName */
4139 case 4: /* directoryName */
4141 SetLastError(CRYPT_E_ASN1_BADTAG
);
4144 case 3: /* x400Address, unimplemented */
4145 case 5: /* ediPartyName, unimplemented */
4146 SetLastError(CRYPT_E_ASN1_BADTAG
);
4150 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4156 *pcbEntry
= bytesNeeded
;
4157 else if (*pcbEntry
< bytesNeeded
)
4159 SetLastError(ERROR_MORE_DATA
);
4164 /* MS used values one greater than the asn1 ones.. sigh */
4165 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
4166 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4168 case 1: /* rfc822Name */
4169 case 2: /* dNSName */
4170 case 6: /* uniformResourceIdentifier */
4174 for (i
= 0; i
< dataLen
; i
++)
4175 entry
->u
.pwszURL
[i
] = (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
4176 entry
->u
.pwszURL
[i
] = 0;
4179 case 7: /* iPAddress */
4180 /* The next data pointer is in the pwszURL spot, that is,
4181 * the first 4 bytes. Need to move it to the next spot.
4183 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
4184 entry
->u
.IPAddress
.cbData
= dataLen
;
4185 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
4195 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
4196 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4197 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4203 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
4207 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4209 DWORD bytesNeeded
, cEntry
= 0;
4210 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4212 bytesNeeded
= sizeof(CERT_ALT_NAME_INFO
);
4217 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4218 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
4222 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4223 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
4229 bytesNeeded
+= size
;
4230 ret
= CRYPT_GetLen(ptr
,
4231 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4233 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
4240 *pcbStructInfo
= bytesNeeded
;
4241 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4242 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4244 CERT_ALT_NAME_INFO
*info
;
4246 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4247 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4248 info
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
4249 info
->cAltEntry
= 0;
4251 info
->rgAltEntry
= NULL
;
4259 (CERT_ALT_NAME_ENTRY
*)((BYTE
*)pvStructInfo
+
4260 sizeof(CERT_ALT_NAME_INFO
));
4261 nextData
= (BYTE
*)info
->rgAltEntry
+
4262 cEntry
* sizeof(CERT_ALT_NAME_ENTRY
);
4263 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4264 i
< cEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
4267 info
->rgAltEntry
[i
].u
.pwszURL
= (LPWSTR
)nextData
;
4269 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4270 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
4271 &info
->rgAltEntry
[i
], &size
);
4278 sizeof(CERT_ALT_NAME_ENTRY
);
4279 bytesNeeded
-= size
;
4280 ret
= CRYPT_GetLen(ptr
,
4281 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4283 ptr
+= nextLen
+ 1 +
4284 GET_LEN_BYTES(ptr
[1]);
4294 SetLastError(CRYPT_E_ASN1_BADTAG
);
4298 __EXCEPT(page_fault
)
4300 SetLastError(STATUS_ACCESS_VIOLATION
);
4307 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
4308 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4309 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4315 if (pbEncoded
[0] == ASN_SEQUENCE
)
4319 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4321 /* sanity-check length, space enough for 7 bytes of integer and
4326 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4331 DWORD bytesNeeded
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
4334 *pcbStructInfo
= bytesNeeded
;
4338 CERT_BASIC_CONSTRAINTS2_INFO info
= { 0 };
4340 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4341 pbEncoded
+= 1 + lenBytes
;
4342 cbEncoded
-= 1 + lenBytes
;
4347 if (pbEncoded
[0] == ASN_BOOL
)
4349 size
= sizeof(BOOL
);
4350 ret
= CRYPT_AsnDecodeBool(dwCertEncodingType
,
4351 NULL
, pbEncoded
, cbEncoded
,
4352 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
4356 cbEncoded
-= 2 + pbEncoded
[1];
4357 pbEncoded
+= 2 + pbEncoded
[1];
4360 if (ret
&& cbEncoded
&& pbEncoded
[0] == ASN_INTEGER
)
4362 size
= sizeof(info
.dwPathLenConstraint
);
4363 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
,
4364 X509_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
,
4365 &info
.dwPathLenConstraint
, &size
);
4368 cbEncoded
-= 2 + pbEncoded
[1];
4369 pbEncoded
+= 2 + pbEncoded
[1];
4372 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4376 info
.fPathLenConstraint
= TRUE
;
4382 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4383 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4386 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4387 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4388 memcpy(pvStructInfo
, &info
,
4389 sizeof(CERT_BASIC_CONSTRAINTS2_INFO
));
4398 SetLastError(CRYPT_E_ASN1_BADTAG
);
4402 __EXCEPT(page_fault
)
4404 SetLastError(STATUS_ACCESS_VIOLATION
);
4411 #define RSA1_MAGIC 0x31415352
4413 struct DECODED_RSA_PUB_KEY
4416 CRYPT_INTEGER_BLOB modulus
;
4419 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4420 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4421 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4427 struct AsnDecodeSequenceItem items
[] = {
4428 { offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4429 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4430 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4432 { offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4433 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4435 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4438 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4439 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4440 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4443 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4444 decodedKey
->modulus
.cbData
;
4448 *pcbStructInfo
= bytesNeeded
;
4451 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4452 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4455 RSAPUBKEY
*rsaPubKey
;
4457 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4458 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4459 hdr
= (BLOBHEADER
*)pvStructInfo
;
4460 hdr
->bType
= PUBLICKEYBLOB
;
4461 hdr
->bVersion
= CUR_BLOB_VERSION
;
4463 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4464 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4465 sizeof(BLOBHEADER
));
4466 rsaPubKey
->magic
= RSA1_MAGIC
;
4467 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4468 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4469 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4470 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4471 decodedKey
->modulus
.cbData
);
4473 LocalFree(decodedKey
);
4476 __EXCEPT(page_fault
)
4478 SetLastError(STATUS_ACCESS_VIOLATION
);
4485 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4486 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4487 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4493 if (pbEncoded
[0] == ASN_OCTETSTRING
)
4495 DWORD bytesNeeded
, dataLen
;
4497 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4499 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4500 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4502 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4504 *pcbStructInfo
= bytesNeeded
;
4505 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4506 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4508 CRYPT_DATA_BLOB
*blob
;
4509 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4511 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4512 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4513 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4514 blob
->cbData
= dataLen
;
4515 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4516 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4519 blob
->pbData
= (BYTE
*)pvStructInfo
+
4520 sizeof(CRYPT_DATA_BLOB
);
4522 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4530 SetLastError(CRYPT_E_ASN1_BADTAG
);
4534 __EXCEPT(page_fault
)
4536 SetLastError(STATUS_ACCESS_VIOLATION
);
4543 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4544 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4545 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4549 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4550 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4552 if (pbEncoded
[0] == ASN_BITSTRING
)
4554 DWORD bytesNeeded
, dataLen
;
4556 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4558 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4559 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4561 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4563 *pcbStructInfo
= bytesNeeded
;
4564 else if (*pcbStructInfo
< bytesNeeded
)
4566 *pcbStructInfo
= bytesNeeded
;
4567 SetLastError(ERROR_MORE_DATA
);
4572 CRYPT_BIT_BLOB
*blob
;
4574 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4575 blob
->cbData
= dataLen
- 1;
4576 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4577 GET_LEN_BYTES(pbEncoded
[1]));
4578 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4580 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4581 GET_LEN_BYTES(pbEncoded
[1]);
4585 assert(blob
->pbData
);
4588 BYTE mask
= 0xff << blob
->cUnusedBits
;
4590 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4591 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4592 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4600 SetLastError(CRYPT_E_ASN1_BADTAG
);
4606 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4607 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4608 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4612 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4613 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4619 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4620 lpszStructType
, pbEncoded
, cbEncoded
,
4621 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4624 *pcbStructInfo
= bytesNeeded
;
4625 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4626 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4628 CRYPT_BIT_BLOB
*blob
;
4630 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4631 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4632 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4633 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4634 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4635 lpszStructType
, pbEncoded
, cbEncoded
,
4636 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4641 __EXCEPT(page_fault
)
4643 SetLastError(STATUS_ACCESS_VIOLATION
);
4650 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4651 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4652 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4658 *pcbStructInfo
= sizeof(int);
4663 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4664 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4665 DWORD size
= sizeof(buf
);
4667 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4668 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4669 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4672 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4673 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4677 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4678 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4679 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4681 /* initialize to a negative value to sign-extend */
4686 for (i
= 0; i
< blob
->cbData
; i
++)
4689 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4691 memcpy(pvStructInfo
, &val
, sizeof(int));
4694 else if (GetLastError() == ERROR_MORE_DATA
)
4695 SetLastError(CRYPT_E_ASN1_LARGE
);
4697 __EXCEPT(page_fault
)
4699 SetLastError(STATUS_ACCESS_VIOLATION
);
4706 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4707 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4708 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4712 if (pbEncoded
[0] == ASN_INTEGER
)
4714 DWORD bytesNeeded
, dataLen
;
4716 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4718 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4720 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4722 *pcbStructInfo
= bytesNeeded
;
4723 else if (*pcbStructInfo
< bytesNeeded
)
4725 *pcbStructInfo
= bytesNeeded
;
4726 SetLastError(ERROR_MORE_DATA
);
4731 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4733 blob
->cbData
= dataLen
;
4734 assert(blob
->pbData
);
4739 for (i
= 0; i
< blob
->cbData
; i
++)
4741 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4750 SetLastError(CRYPT_E_ASN1_BADTAG
);
4756 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4757 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4758 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4766 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4767 lpszStructType
, pbEncoded
, cbEncoded
,
4768 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4771 *pcbStructInfo
= bytesNeeded
;
4772 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4773 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4775 CRYPT_INTEGER_BLOB
*blob
;
4777 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4778 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4779 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4780 blob
->pbData
= (BYTE
*)pvStructInfo
+
4781 sizeof(CRYPT_INTEGER_BLOB
);
4782 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4783 lpszStructType
, pbEncoded
, cbEncoded
,
4784 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4789 __EXCEPT(page_fault
)
4791 SetLastError(STATUS_ACCESS_VIOLATION
);
4798 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4799 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4800 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4806 if (pbEncoded
[0] == ASN_INTEGER
)
4808 DWORD bytesNeeded
, dataLen
;
4809 CRYPT_INTEGER_BLOB
*blob
;
4811 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4813 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4815 *pcbStructInfo
= bytesNeeded
;
4816 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4817 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4819 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4821 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4822 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4823 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4824 blob
->cbData
= dataLen
;
4825 blob
->pbData
= (BYTE
*)pvStructInfo
+
4826 sizeof(CRYPT_INTEGER_BLOB
);
4827 /* remove leading zero byte if it exists */
4828 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4837 for (i
= 0; i
< blob
->cbData
; i
++)
4838 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4839 pbEncoded
[1] - i
- 1);
4846 SetLastError(CRYPT_E_ASN1_BADTAG
);
4850 __EXCEPT(page_fault
)
4852 SetLastError(STATUS_ACCESS_VIOLATION
);
4859 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4860 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4861 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4867 *pcbStructInfo
= sizeof(int);
4872 if (pbEncoded
[0] == ASN_ENUMERATED
)
4874 unsigned int val
= 0, i
;
4878 SetLastError(CRYPT_E_ASN1_EOD
);
4881 else if (pbEncoded
[1] == 0)
4883 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4888 /* A little strange looking, but we have to accept a sign byte:
4889 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4890 * assuming a small length is okay here, it has to be in short
4893 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4895 SetLastError(CRYPT_E_ASN1_LARGE
);
4898 for (i
= 0; i
< pbEncoded
[1]; i
++)
4901 val
|= pbEncoded
[2 + i
];
4903 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4904 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4906 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4907 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4908 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4914 SetLastError(CRYPT_E_ASN1_BADTAG
);
4918 __EXCEPT(page_fault
)
4920 SetLastError(STATUS_ACCESS_VIOLATION
);
4927 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4930 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4935 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4937 if (!isdigit(*(pbEncoded))) \
4939 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4945 (word) += *(pbEncoded)++ - '0'; \
4950 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
4951 SYSTEMTIME
*sysTime
)
4957 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
4959 WORD hours
, minutes
= 0;
4960 BYTE sign
= *pbEncoded
++;
4963 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
4964 if (ret
&& hours
>= 24)
4966 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4971 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
4972 if (ret
&& minutes
>= 60)
4974 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4982 sysTime
->wHour
+= hours
;
4983 sysTime
->wMinute
+= minutes
;
4987 if (hours
> sysTime
->wHour
)
4990 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
4993 sysTime
->wHour
-= hours
;
4994 if (minutes
> sysTime
->wMinute
)
4997 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
5000 sysTime
->wMinute
-= minutes
;
5005 __EXCEPT(page_fault
)
5007 SetLastError(STATUS_ACCESS_VIOLATION
);
5014 #define MIN_ENCODED_TIME_LENGTH 10
5016 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
5017 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5018 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5024 *pcbStructInfo
= sizeof(FILETIME
);
5029 if (pbEncoded
[0] == ASN_UTCTIME
)
5033 SetLastError(CRYPT_E_ASN1_EOD
);
5036 else if (pbEncoded
[1] > 0x7f)
5038 /* long-form date strings really can't be valid */
5039 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5044 SYSTEMTIME sysTime
= { 0 };
5045 BYTE len
= pbEncoded
[1];
5047 if (len
< MIN_ENCODED_TIME_LENGTH
)
5049 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5055 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
5056 if (sysTime
.wYear
>= 50)
5057 sysTime
.wYear
+= 1900;
5059 sysTime
.wYear
+= 2000;
5060 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5061 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5062 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5063 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
5066 if (len
>= 2 && isdigit(*pbEncoded
) &&
5067 isdigit(*(pbEncoded
+ 1)))
5068 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5070 else if (isdigit(*pbEncoded
))
5071 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
5074 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5077 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5078 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5081 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5082 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5083 ret
= SystemTimeToFileTime(&sysTime
,
5084 (FILETIME
*)pvStructInfo
);
5091 SetLastError(CRYPT_E_ASN1_BADTAG
);
5095 __EXCEPT(page_fault
)
5097 SetLastError(STATUS_ACCESS_VIOLATION
);
5104 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
5105 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5106 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5112 *pcbStructInfo
= sizeof(FILETIME
);
5117 if (pbEncoded
[0] == ASN_GENERALTIME
)
5121 SetLastError(CRYPT_E_ASN1_EOD
);
5124 else if (pbEncoded
[1] > 0x7f)
5126 /* long-form date strings really can't be valid */
5127 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5132 BYTE len
= pbEncoded
[1];
5134 if (len
< MIN_ENCODED_TIME_LENGTH
)
5136 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5141 SYSTEMTIME sysTime
= { 0 };
5144 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
5145 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5146 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5147 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5150 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5153 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5155 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
5162 /* workaround macro weirdness */
5163 digits
= min(len
, 3);
5164 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
5165 sysTime
.wMilliseconds
);
5168 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5171 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5172 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5175 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5176 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5177 ret
= SystemTimeToFileTime(&sysTime
,
5178 (FILETIME
*)pvStructInfo
);
5185 SetLastError(CRYPT_E_ASN1_BADTAG
);
5189 __EXCEPT(page_fault
)
5191 SetLastError(STATUS_ACCESS_VIOLATION
);
5198 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5199 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5200 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5206 if (pbEncoded
[0] == ASN_UTCTIME
)
5207 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5208 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5210 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5211 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5212 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5213 pvStructInfo
, pcbStructInfo
);
5216 SetLastError(CRYPT_E_ASN1_BADTAG
);
5220 __EXCEPT(page_fault
)
5222 SetLastError(STATUS_ACCESS_VIOLATION
);
5229 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5230 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5231 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5237 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5239 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5241 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5246 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5247 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5249 ptr
= pbEncoded
+ 1 + lenBytes
;
5250 remainingLen
= dataLen
;
5251 while (ret
&& remainingLen
)
5255 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5258 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5260 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5261 ptr
+= 1 + nextLenBytes
+ nextLen
;
5262 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5263 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5264 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5270 CRYPT_SEQUENCE_OF_ANY
*seq
;
5274 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5275 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5277 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5278 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5279 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5280 seq
->cValue
= cValue
;
5281 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5283 nextPtr
= (BYTE
*)seq
->rgValue
+
5284 cValue
* sizeof(CRYPT_DER_BLOB
);
5285 ptr
= pbEncoded
+ 1 + lenBytes
;
5286 remainingLen
= dataLen
;
5288 while (ret
&& remainingLen
)
5292 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5295 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5297 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5299 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5300 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5303 seq
->rgValue
[i
].pbData
= nextPtr
;
5304 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5306 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5308 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5309 ptr
+= 1 + nextLenBytes
+ nextLen
;
5319 SetLastError(CRYPT_E_ASN1_BADTAG
);
5323 __EXCEPT(page_fault
)
5325 SetLastError(STATUS_ACCESS_VIOLATION
);
5332 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5333 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5334 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5338 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5340 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5341 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5342 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5344 if (!pvStructInfo
&& !pcbStructInfo
)
5346 SetLastError(ERROR_INVALID_PARAMETER
);
5349 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5350 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5352 SetLastError(ERROR_FILE_NOT_FOUND
);
5357 SetLastError(CRYPT_E_ASN1_EOD
);
5360 if (cbEncoded
> MAX_ENCODED_LEN
)
5362 SetLastError(CRYPT_E_ASN1_LARGE
);
5366 SetLastError(NOERROR
);
5367 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5368 *(BYTE
**)pvStructInfo
= NULL
;
5369 if (!HIWORD(lpszStructType
))
5371 switch (LOWORD(lpszStructType
))
5373 case (WORD
)X509_CERT
:
5374 decodeFunc
= CRYPT_AsnDecodeCert
;
5376 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5377 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5379 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5380 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5382 case (WORD
)X509_EXTENSIONS
:
5383 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5385 case (WORD
)X509_NAME
:
5386 decodeFunc
= CRYPT_AsnDecodeName
;
5388 case (WORD
)X509_PUBLIC_KEY_INFO
:
5389 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5391 case (WORD
)X509_ALTERNATE_NAME
:
5392 decodeFunc
= CRYPT_AsnDecodeAltName
;
5394 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5395 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5397 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5398 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5400 case (WORD
)X509_OCTET_STRING
:
5401 decodeFunc
= CRYPT_AsnDecodeOctets
;
5403 case (WORD
)X509_BITS
:
5404 case (WORD
)X509_KEY_USAGE
:
5405 decodeFunc
= CRYPT_AsnDecodeBits
;
5407 case (WORD
)X509_INTEGER
:
5408 decodeFunc
= CRYPT_AsnDecodeInt
;
5410 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5411 decodeFunc
= CRYPT_AsnDecodeInteger
;
5413 case (WORD
)X509_MULTI_BYTE_UINT
:
5414 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5416 case (WORD
)X509_ENUMERATED
:
5417 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5419 case (WORD
)X509_CHOICE_OF_TIME
:
5420 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5422 case (WORD
)X509_SEQUENCE_OF_ANY
:
5423 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5425 case (WORD
)PKCS_UTC_TIME
:
5426 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5429 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5432 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5433 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5434 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5435 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5436 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5437 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5438 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5439 decodeFunc
= CRYPT_AsnDecodeBits
;
5440 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5441 decodeFunc
= CRYPT_AsnDecodeOctets
;
5442 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5443 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5444 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5445 decodeFunc
= CRYPT_AsnDecodeAltName
;
5446 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5447 decodeFunc
= CRYPT_AsnDecodeAltName
;
5448 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5449 decodeFunc
= CRYPT_AsnDecodeAltName
;
5450 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5451 decodeFunc
= CRYPT_AsnDecodeAltName
;
5452 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5453 decodeFunc
= CRYPT_AsnDecodeAltName
;
5455 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5456 debugstr_a(lpszStructType
));
5458 decodeFunc
= (CryptDecodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
5459 lpszStructType
, "CryptDecodeObjectEx", &lib
);
5461 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5462 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5464 SetLastError(ERROR_FILE_NOT_FOUND
);