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_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
121 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
122 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
123 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
125 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
126 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
127 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
128 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
129 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
130 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
131 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
132 * time, doesn't do memory allocation, and doesn't do exception handling.
133 * (This isn't intended to be the externally-called one.)
135 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
136 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
137 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
138 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
139 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
);
140 /* Assumes algo->Parameters.pbData is set ahead of time */
141 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(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_AsnDecodeBool(DWORD dwCertEncodingType
,
145 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
146 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
147 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
148 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
149 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
150 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
151 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
152 * member has been initialized, doesn't do exception handling, and doesn't do
155 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
156 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
157 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
158 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
159 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
160 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
161 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
162 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
163 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
164 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
165 * member has been initialized, doesn't do exception handling, and doesn't do
168 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
169 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
170 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
171 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
172 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
173 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
174 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
175 void *pvStructInfo
, DWORD
*pcbStructInfo
);
177 /* filter for page-fault exceptions */
178 static WINE_EXCEPTION_FILTER(page_fault
)
180 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
181 return EXCEPTION_EXECUTE_HANDLER
;
182 return EXCEPTION_CONTINUE_SEARCH
;
185 static char *CRYPT_GetKeyName(DWORD dwEncodingType
, LPCSTR pszFuncName
,
188 static const char szEncodingTypeFmt
[] =
189 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
191 char numericOID
[7]; /* enough for "#65535" */
195 /* MSDN says the encoding type is a mask, but it isn't treated that way.
196 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
197 * "EncodingType 2" would be expected if it were a mask. Instead native
198 * stores values in "EncodingType 3".
202 snprintf(numericOID
, sizeof(numericOID
), "#%d", LOWORD(pszOID
));
208 /* This is enough: the lengths of the two string parameters are explicitly
209 * counted, and we need up to five additional characters for the encoding
210 * type. These are covered by the "%d", "%s", and "%s" characters in the
211 * format specifier that are removed by sprintf.
213 len
= sizeof(szEncodingTypeFmt
) + lstrlenA(pszFuncName
) + lstrlenA(oid
);
214 szKey
= HeapAlloc(GetProcessHeap(), 0, len
);
216 sprintf(szKey
, szEncodingTypeFmt
, dwEncodingType
, pszFuncName
, oid
);
220 BOOL WINAPI
CryptRegisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
221 LPCSTR pszOID
, LPCWSTR pwszDll
, LPCSTR pszOverrideFuncName
)
227 TRACE("%lx %s %s %s %s\n", dwEncodingType
, pszFuncName
, pszOID
,
228 debugstr_w(pwszDll
), pszOverrideFuncName
);
230 /* This only registers functions for encoding certs, not messages */
231 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
234 /* Native does nothing pwszDll is NULL */
238 /* I'm not matching MS bug for bug here, because I doubt any app depends on
240 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
241 * it creates would never be used
242 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
243 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
245 if (!pszFuncName
|| !pszOID
)
247 SetLastError(ERROR_INVALID_PARAMETER
);
251 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
252 TRACE("Key name is %s\n", debugstr_a(szKey
));
257 r
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
258 HeapFree(GetProcessHeap(), 0, szKey
);
259 if(r
!= ERROR_SUCCESS
)
262 /* write the values */
263 if (pszOverrideFuncName
)
264 RegSetValueExA(hKey
, "FuncName", 0, REG_SZ
, (const BYTE
*)pszOverrideFuncName
,
265 lstrlenA(pszOverrideFuncName
) + 1);
266 RegSetValueExW(hKey
, szDllName
, 0, REG_SZ
, (const BYTE
*) pwszDll
,
267 (lstrlenW(pwszDll
) + 1) * sizeof (WCHAR
));
273 BOOL WINAPI
CryptUnregisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
279 TRACE("%lx %s %s\n", dwEncodingType
, pszFuncName
, pszOID
);
281 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
284 if (!pszFuncName
|| !pszOID
)
286 SetLastError(ERROR_INVALID_PARAMETER
);
290 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
291 rc
= RegDeleteKeyA(HKEY_LOCAL_MACHINE
, szKey
);
292 HeapFree(GetProcessHeap(), 0, szKey
);
295 return rc
? FALSE
: TRUE
;
298 BOOL WINAPI
CryptGetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
299 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD
*pdwValueType
, BYTE
*pbValueData
,
306 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType
, debugstr_a(pszFuncName
),
307 debugstr_a(pszOID
), debugstr_w(pwszValueName
), pdwValueType
, pbValueData
,
310 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
313 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
315 SetLastError(ERROR_INVALID_PARAMETER
);
319 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
320 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
321 HeapFree(GetProcessHeap(), 0, szKey
);
326 rc
= RegQueryValueExW(hKey
, pwszValueName
, NULL
, pdwValueType
,
327 pbValueData
, pcbValueData
);
332 return rc
? FALSE
: TRUE
;
335 BOOL WINAPI
CryptSetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
336 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD dwValueType
,
337 const BYTE
*pbValueData
, DWORD cbValueData
)
343 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType
, debugstr_a(pszFuncName
),
344 debugstr_a(pszOID
), debugstr_w(pwszValueName
), dwValueType
, pbValueData
,
347 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
350 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
352 SetLastError(ERROR_INVALID_PARAMETER
);
356 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
357 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
358 HeapFree(GetProcessHeap(), 0, szKey
);
363 rc
= RegSetValueExW(hKey
, pwszValueName
, 0, dwValueType
, pbValueData
,
369 return rc
? FALSE
: TRUE
;
372 /* Gets the registered function named szFuncName for dwCertEncodingType and
373 * lpszStructType, or NULL if one could not be found. *lib will be set to the
374 * handle of the module it's in, or NULL if no module was loaded. If the
375 * return value is NULL, *lib will also be NULL, to simplify error handling.
377 static void *CRYPT_GetFunc(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
378 LPCSTR szFuncName
, HMODULE
*lib
)
381 char *szKey
= CRYPT_GetKeyName(dwCertEncodingType
, szFuncName
,
383 const char *funcName
;
386 DWORD type
, size
= 0;
388 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType
, debugstr_a(lpszStructType
),
389 debugstr_a(szFuncName
), lib
);
392 r
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
393 HeapFree(GetProcessHeap(), 0, szKey
);
394 if(r
!= ERROR_SUCCESS
)
397 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, NULL
, &size
);
398 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
400 funcName
= HeapAlloc(GetProcessHeap(), 0, size
);
401 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, (LPBYTE
)funcName
,
405 funcName
= szFuncName
;
406 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, NULL
, &size
);
407 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
409 LPWSTR dllName
= HeapAlloc(GetProcessHeap(), 0, size
);
411 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, (LPBYTE
)dllName
,
413 *lib
= LoadLibraryW(dllName
);
416 ret
= GetProcAddress(*lib
, funcName
);
419 /* Unload the library, the caller doesn't want to unload it
420 * when the return value is NULL.
426 HeapFree(GetProcessHeap(), 0, dllName
);
428 if (funcName
!= szFuncName
)
429 HeapFree(GetProcessHeap(), 0, (char *)funcName
);
430 TRACE("returning %p\n", ret
);
434 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
435 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
439 CryptEncodeObjectFunc pCryptEncodeObject
;
441 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
442 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
445 if (!pbEncoded
&& !pcbEncoded
)
447 SetLastError(ERROR_INVALID_PARAMETER
);
451 /* Try registered DLL first.. */
453 (CryptEncodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
454 lpszStructType
, "CryptEncodeObject", &lib
);
455 if (pCryptEncodeObject
)
457 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
458 pvStructInfo
, pbEncoded
, pcbEncoded
);
463 /* If not, use CryptEncodeObjectEx */
464 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
465 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
470 /* Helper function to check *pcbEncoded, set it to the required size, and
471 * optionally to allocate memory. Assumes pbEncoded is not NULL.
472 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
473 * pointer to the newly allocated memory.
475 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
476 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
481 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
483 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
484 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
486 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
487 if (!*(BYTE
**)pbEncoded
)
490 *pcbEncoded
= bytesNeeded
;
492 else if (bytesNeeded
> *pcbEncoded
)
494 *pcbEncoded
= bytesNeeded
;
495 SetLastError(ERROR_MORE_DATA
);
501 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
503 DWORD bytesNeeded
, significantBytes
= 0;
511 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
512 temp
<<= 8, significantBytes
--)
514 bytesNeeded
= significantBytes
+ 1;
518 *pcbEncoded
= bytesNeeded
;
521 if (*pcbEncoded
< bytesNeeded
)
523 SetLastError(ERROR_MORE_DATA
);
527 *pbEncoded
= (BYTE
)len
;
532 *pbEncoded
++ = significantBytes
| 0x80;
533 for (i
= 0; i
< significantBytes
; i
++)
535 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
539 *pcbEncoded
= bytesNeeded
;
543 struct AsnEncodeSequenceItem
545 const void *pvStructInfo
;
546 CryptEncodeObjectExFunc encodeFunc
;
547 DWORD size
; /* used during encoding, not for your use */
550 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
551 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
552 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
555 DWORD i
, dataLen
= 0;
557 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
558 pbEncoded
, *pcbEncoded
);
559 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
561 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
562 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
563 NULL
, &items
[i
].size
);
564 dataLen
+= items
[i
].size
;
568 DWORD lenBytes
, bytesNeeded
;
570 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
571 bytesNeeded
= 1 + lenBytes
+ dataLen
;
573 *pcbEncoded
= bytesNeeded
;
576 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
577 pcbEncoded
, bytesNeeded
)))
579 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
580 pbEncoded
= *(BYTE
**)pbEncoded
;
581 *pbEncoded
++ = ASN_SEQUENCE
;
582 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
583 pbEncoded
+= lenBytes
;
584 for (i
= 0; ret
&& i
< cItem
; i
++)
586 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
587 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
588 NULL
, pbEncoded
, &items
[i
].size
);
589 pbEncoded
+= items
[i
].size
;
594 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
598 struct AsnConstructedItem
601 const void *pvStructInfo
;
602 CryptEncodeObjectExFunc encodeFunc
;
605 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
606 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
607 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
610 const struct AsnConstructedItem
*item
=
611 (const struct AsnConstructedItem
*)pvStructInfo
;
614 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
615 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
617 DWORD dataLen
, bytesNeeded
;
619 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
620 bytesNeeded
= 1 + dataLen
+ len
;
622 *pcbEncoded
= bytesNeeded
;
623 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
624 pbEncoded
, pcbEncoded
, bytesNeeded
)))
626 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
627 pbEncoded
= *(BYTE
**)pbEncoded
;
628 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
629 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
630 pbEncoded
+= dataLen
;
631 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
632 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
639 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
640 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
641 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
643 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
646 /* CERT_V1 is not encoded */
654 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
656 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
657 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
662 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
663 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
664 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
666 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
671 *pcbEncoded
= blob
->cbData
;
674 else if (*pcbEncoded
< blob
->cbData
)
676 *pcbEncoded
= blob
->cbData
;
677 SetLastError(ERROR_MORE_DATA
);
683 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
684 *pcbEncoded
= blob
->cbData
;
690 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
691 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
692 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
695 /* This has two filetimes in a row, a NotBefore and a NotAfter */
696 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
697 struct AsnEncodeSequenceItem items
[] = {
698 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
699 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
702 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
703 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
708 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
709 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
710 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
713 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
714 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
716 struct AsnEncodeSequenceItem items
[] = {
717 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
718 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
721 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
722 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
727 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
728 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
729 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
735 const CERT_PUBLIC_KEY_INFO
*info
=
736 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
737 struct AsnEncodeSequenceItem items
[] = {
738 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
739 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
742 TRACE("Encoding public key with OID %s\n",
743 debugstr_a(info
->Algorithm
.pszObjId
));
744 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
745 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
750 SetLastError(STATUS_ACCESS_VIOLATION
);
757 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
758 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
759 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
765 const CERT_SIGNED_CONTENT_INFO
*info
=
766 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
767 struct AsnEncodeSequenceItem items
[] = {
768 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
769 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
770 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
773 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
774 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
775 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
776 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
781 SetLastError(STATUS_ACCESS_VIOLATION
);
788 /* Like in Windows, this blithely ignores the validity of the passed-in
789 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
790 * decode properly, see CRYPT_AsnDecodeCertInfo.
792 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
793 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
794 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
800 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
801 struct AsnEncodeSequenceItem items
[10] = {
802 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
803 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
804 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
805 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
806 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
807 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
808 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
811 struct AsnConstructedItem constructed
[3] = { { 0 } };
812 DWORD cItem
= 7, cConstructed
= 0;
814 if (info
->IssuerUniqueId
.cbData
)
816 constructed
[cConstructed
].tag
= 1;
817 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
818 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
819 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
820 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
824 if (info
->SubjectUniqueId
.cbData
)
826 constructed
[cConstructed
].tag
= 2;
827 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
828 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
829 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
830 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
834 if (info
->cExtension
)
836 constructed
[cConstructed
].tag
= 3;
837 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
838 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
839 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
840 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
845 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
846 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
850 SetLastError(STATUS_ACCESS_VIOLATION
);
857 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
858 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
860 struct AsnEncodeSequenceItem items
[3] = {
861 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
862 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
868 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
870 if (entry
->cExtension
)
872 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
873 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
877 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
878 pbEncoded
, pcbEncoded
);
880 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
884 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
885 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
886 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
888 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
889 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
890 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
891 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
894 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
898 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
902 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
903 bytesNeeded
= 1 + lenBytes
+ dataLen
;
905 *pcbEncoded
= bytesNeeded
;
908 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
909 pcbEncoded
, bytesNeeded
)))
911 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
912 pbEncoded
= *(BYTE
**)pbEncoded
;
913 *pbEncoded
++ = ASN_SEQUENCEOF
;
914 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
915 pbEncoded
+= lenBytes
;
916 for (i
= 0; i
< cCRLEntry
; i
++)
918 DWORD size
= dataLen
;
920 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
929 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
930 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
931 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
933 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
936 /* CRL_V1 is not encoded */
943 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
944 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
948 /* Like in Windows, this blithely ignores the validity of the passed-in
949 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
950 * decode properly, see CRYPT_AsnDecodeCRLInfo.
952 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
953 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
954 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
960 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
961 struct AsnEncodeSequenceItem items
[7] = {
962 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
963 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
964 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
965 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
970 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
972 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
973 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
978 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
979 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
982 if (info
->cExtension
)
984 items
[cItem
].pvStructInfo
= &info
->cExtension
;
985 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
989 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
990 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
994 SetLastError(STATUS_ACCESS_VIOLATION
);
1001 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
1005 struct AsnEncodeSequenceItem items
[3] = {
1006 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
1012 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
1016 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
1017 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1020 items
[cItem
].pvStructInfo
= &ext
->Value
;
1021 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1024 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
1025 pbEncoded
, pcbEncoded
);
1026 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1030 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
1031 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1032 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1038 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1039 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
1042 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
1046 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
1050 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1051 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1053 *pcbEncoded
= bytesNeeded
;
1056 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1057 pcbEncoded
, bytesNeeded
)))
1059 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1060 pbEncoded
= *(BYTE
**)pbEncoded
;
1061 *pbEncoded
++ = ASN_SEQUENCEOF
;
1062 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1063 pbEncoded
+= lenBytes
;
1064 for (i
= 0; i
< exts
->cExtension
; i
++)
1066 DWORD size
= dataLen
;
1068 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
1076 __EXCEPT(page_fault
)
1078 SetLastError(STATUS_ACCESS_VIOLATION
);
1085 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
1086 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1087 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1089 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
1090 DWORD bytesNeeded
= 0, lenBytes
;
1095 TRACE("%s\n", debugstr_a(pszObjId
));
1102 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
1104 SetLastError(CRYPT_E_ASN1_ERROR
);
1108 firstByte
= val1
* 40 + val2
;
1109 ptr
= pszObjId
+ firstPos
;
1114 /* note I assume each component is at most 32-bits long in base 2 */
1115 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
1117 if (val1
>= 0x10000000)
1119 else if (val1
>= 0x200000)
1121 else if (val1
>= 0x4000)
1123 else if (val1
>= 0x80)
1133 SetLastError(CRYPT_E_ASN1_ERROR
);
1137 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1141 bytesNeeded
+= 1 + lenBytes
;
1144 if (*pcbEncoded
< bytesNeeded
)
1146 SetLastError(ERROR_MORE_DATA
);
1151 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
1152 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
1153 pbEncoded
+= lenBytes
;
1159 *pbEncoded
++ = firstByte
;
1160 ptr
= pszObjId
+ firstPos
;
1163 sscanf(ptr
, "%d%n", &val
, &pos
);
1165 unsigned char outBytes
[5];
1168 if (val
>= 0x10000000)
1170 else if (val
>= 0x200000)
1172 else if (val
>= 0x4000)
1174 else if (val
>= 0x80)
1178 for (i
= numBytes
; i
> 0; i
--)
1180 outBytes
[i
- 1] = val
& 0x7f;
1183 for (i
= 0; i
< numBytes
- 1; i
++)
1184 *pbEncoded
++ = outBytes
[i
] | 0x80;
1185 *pbEncoded
++ = outBytes
[i
];
1194 *pcbEncoded
= bytesNeeded
;
1198 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1199 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1202 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1205 switch (value
->dwValueType
)
1207 case CERT_RDN_NUMERIC_STRING
:
1208 tag
= ASN_NUMERICSTRING
;
1209 encodedLen
= value
->Value
.cbData
;
1211 case CERT_RDN_PRINTABLE_STRING
:
1212 tag
= ASN_PRINTABLESTRING
;
1213 encodedLen
= value
->Value
.cbData
;
1215 case CERT_RDN_IA5_STRING
:
1216 tag
= ASN_IA5STRING
;
1217 encodedLen
= value
->Value
.cbData
;
1219 case CERT_RDN_ANY_TYPE
:
1220 /* explicitly disallowed */
1221 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1224 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
1227 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1228 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1231 if (*pcbEncoded
< bytesNeeded
)
1233 SetLastError(ERROR_MORE_DATA
);
1239 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1240 pbEncoded
+= lenBytes
;
1241 switch (value
->dwValueType
)
1243 case CERT_RDN_NUMERIC_STRING
:
1244 case CERT_RDN_PRINTABLE_STRING
:
1245 case CERT_RDN_IA5_STRING
:
1246 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1250 *pcbEncoded
= bytesNeeded
;
1254 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1255 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1257 DWORD bytesNeeded
= 0, lenBytes
, size
;
1260 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1261 0, NULL
, NULL
, &size
);
1264 bytesNeeded
+= size
;
1265 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1266 * with dwValueType, so "cast" it to get its encoded size
1268 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1269 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1272 bytesNeeded
+= size
;
1273 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1274 bytesNeeded
+= 1 + lenBytes
;
1277 if (*pcbEncoded
< bytesNeeded
)
1279 SetLastError(ERROR_MORE_DATA
);
1284 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SEQUENCE
;
1285 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1287 pbEncoded
+= lenBytes
;
1288 size
= bytesNeeded
- 1 - lenBytes
;
1289 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1290 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1294 size
= bytesNeeded
- 1 - lenBytes
- size
;
1295 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1296 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1301 *pcbEncoded
= bytesNeeded
;
1307 static int BLOBComp(const void *l
, const void *r
)
1309 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1312 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1313 ret
= a
->cbData
- b
->cbData
;
1317 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1319 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1320 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1323 CRYPT_DER_BLOB
*blobs
= NULL
;
1327 DWORD bytesNeeded
= 0, lenBytes
, i
;
1333 blobs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1334 rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1338 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1340 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1341 NULL
, &blobs
[i
].cbData
);
1343 bytesNeeded
+= blobs
[i
].cbData
;
1347 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1348 bytesNeeded
+= 1 + lenBytes
;
1351 if (*pcbEncoded
< bytesNeeded
)
1353 SetLastError(ERROR_MORE_DATA
);
1358 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1360 blobs
[i
].pbData
= HeapAlloc(GetProcessHeap(), 0,
1362 if (!blobs
[i
].pbData
)
1365 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1366 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1371 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1373 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1374 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1376 pbEncoded
+= lenBytes
;
1377 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1379 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1380 pbEncoded
+= blobs
[i
].cbData
;
1385 *pcbEncoded
= bytesNeeded
;
1389 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1390 HeapFree(GetProcessHeap(), 0, blobs
[i
].pbData
);
1393 __EXCEPT(page_fault
)
1395 SetLastError(STATUS_ACCESS_VIOLATION
);
1399 HeapFree(GetProcessHeap(), 0, blobs
);
1403 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1404 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1405 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1411 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1412 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1414 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1416 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1418 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1421 bytesNeeded
+= size
;
1423 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1424 bytesNeeded
+= 1 + lenBytes
;
1428 *pcbEncoded
= bytesNeeded
;
1431 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1432 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1434 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1435 pbEncoded
= *(BYTE
**)pbEncoded
;
1436 *pbEncoded
++ = ASN_SEQUENCEOF
;
1437 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1439 pbEncoded
+= lenBytes
;
1440 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1443 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1444 &info
->rgRDN
[i
], pbEncoded
, &size
);
1448 bytesNeeded
-= size
;
1455 __EXCEPT(page_fault
)
1457 SetLastError(STATUS_ACCESS_VIOLATION
);
1464 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1465 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1466 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1468 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1477 else if (*pcbEncoded
< 3)
1480 SetLastError(ERROR_MORE_DATA
);
1486 *pbEncoded
++ = ASN_BOOL
;
1488 *pbEncoded
++ = val
? 0xff : 0;
1491 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1495 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1496 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1502 switch (entry
->dwAltNameChoice
)
1504 case CERT_ALT_NAME_RFC822_NAME
:
1505 case CERT_ALT_NAME_DNS_NAME
:
1506 case CERT_ALT_NAME_URL
:
1507 if (entry
->u
.pwszURL
)
1511 /* Not + 1: don't encode the NULL-terminator */
1512 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1513 for (i
= 0; ret
&& i
< dataLen
; i
++)
1515 if (entry
->u
.pwszURL
[i
] > 0x7f)
1517 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1526 case CERT_ALT_NAME_IP_ADDRESS
:
1527 dataLen
= entry
->u
.IPAddress
.cbData
;
1529 case CERT_ALT_NAME_REGISTERED_ID
:
1530 /* FIXME: encode OID */
1531 case CERT_ALT_NAME_OTHER_NAME
:
1532 case CERT_ALT_NAME_DIRECTORY_NAME
:
1533 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1536 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1541 DWORD bytesNeeded
, lenBytes
;
1543 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1544 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1546 *pcbEncoded
= bytesNeeded
;
1547 else if (*pcbEncoded
< bytesNeeded
)
1549 SetLastError(ERROR_MORE_DATA
);
1550 *pcbEncoded
= bytesNeeded
;
1555 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1556 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1557 pbEncoded
+= lenBytes
;
1558 switch (entry
->dwAltNameChoice
)
1560 case CERT_ALT_NAME_RFC822_NAME
:
1561 case CERT_ALT_NAME_DNS_NAME
:
1562 case CERT_ALT_NAME_URL
:
1566 for (i
= 0; i
< dataLen
; i
++)
1567 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1570 case CERT_ALT_NAME_IP_ADDRESS
:
1571 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1575 *pcbEncoded
= bytesNeeded
;
1578 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1582 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1583 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1584 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1590 const CERT_ALT_NAME_INFO
*info
=
1591 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1593 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1596 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1597 * can't encode an erroneous entry index if it's bigger than this.
1599 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1603 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1607 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1609 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1610 * the bad character, now set the index of the bad
1613 *pcbEncoded
= (BYTE
)i
<<
1614 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1619 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1620 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1623 *pcbEncoded
= bytesNeeded
;
1628 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1629 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1631 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1632 pbEncoded
= *(BYTE
**)pbEncoded
;
1633 *pbEncoded
++ = ASN_SEQUENCEOF
;
1634 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1635 pbEncoded
+= lenBytes
;
1636 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1638 DWORD len
= dataLen
;
1640 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1652 __EXCEPT(page_fault
)
1654 SetLastError(STATUS_ACCESS_VIOLATION
);
1661 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1662 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1663 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1669 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1670 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1671 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1676 items
[cItem
].pvStructInfo
= &info
->fCA
;
1677 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1680 if (info
->fPathLenConstraint
)
1682 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1683 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1686 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1687 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1689 __EXCEPT(page_fault
)
1691 SetLastError(STATUS_ACCESS_VIOLATION
);
1698 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1699 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1700 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1706 const BLOBHEADER
*hdr
=
1707 (const BLOBHEADER
*)pvStructInfo
;
1709 if (hdr
->bType
!= PUBLICKEYBLOB
)
1711 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1716 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1717 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1718 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1719 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1720 struct AsnEncodeSequenceItem items
[] = {
1721 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1722 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1725 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1726 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1730 __EXCEPT(page_fault
)
1732 SetLastError(STATUS_ACCESS_VIOLATION
);
1739 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1740 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1741 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1747 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1748 DWORD bytesNeeded
, lenBytes
;
1750 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1751 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1753 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1754 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1757 *pcbEncoded
= bytesNeeded
;
1762 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1763 pcbEncoded
, bytesNeeded
)))
1765 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1766 pbEncoded
= *(BYTE
**)pbEncoded
;
1767 *pbEncoded
++ = ASN_OCTETSTRING
;
1768 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1769 pbEncoded
+= lenBytes
;
1771 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1775 __EXCEPT(page_fault
)
1777 SetLastError(STATUS_ACCESS_VIOLATION
);
1781 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1785 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1786 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1787 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1793 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1794 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1797 /* yep, MS allows cUnusedBits to be >= 8 */
1798 if (!blob
->cUnusedBits
)
1800 dataBytes
= blob
->cbData
;
1803 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1805 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1806 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1814 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1815 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1818 *pcbEncoded
= bytesNeeded
;
1823 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1824 pcbEncoded
, bytesNeeded
)))
1826 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1827 pbEncoded
= *(BYTE
**)pbEncoded
;
1828 *pbEncoded
++ = ASN_BITSTRING
;
1829 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1830 pbEncoded
+= lenBytes
;
1831 *pbEncoded
++ = unusedBits
;
1834 BYTE mask
= 0xff << unusedBits
;
1838 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1839 pbEncoded
+= dataBytes
- 1;
1841 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1846 __EXCEPT(page_fault
)
1848 SetLastError(STATUS_ACCESS_VIOLATION
);
1855 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1856 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1857 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1863 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1864 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1869 newBlob
.pbData
= HeapAlloc(GetProcessHeap(), 0, newBlob
.cbData
);
1874 for (i
= 0; i
< newBlob
.cbData
; i
++)
1875 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1881 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1882 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1883 HeapFree(GetProcessHeap(), 0, newBlob
.pbData
);
1885 __EXCEPT(page_fault
)
1887 SetLastError(STATUS_ACCESS_VIOLATION
);
1894 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1895 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1896 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1898 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1900 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1901 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1904 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1905 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1906 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1912 DWORD significantBytes
, lenBytes
;
1913 BYTE padByte
= 0, bytesNeeded
;
1915 const CRYPT_INTEGER_BLOB
*blob
=
1916 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1918 significantBytes
= blob
->cbData
;
1919 if (significantBytes
)
1921 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1923 /* negative, lop off leading (little-endian) 0xffs */
1924 for (; significantBytes
> 0 &&
1925 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1927 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1935 /* positive, lop off leading (little-endian) zeroes */
1936 for (; significantBytes
> 0 &&
1937 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1939 if (significantBytes
== 0)
1940 significantBytes
= 1;
1941 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1949 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1951 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1952 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1957 *pcbEncoded
= bytesNeeded
;
1962 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1963 pcbEncoded
, bytesNeeded
)))
1965 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1966 pbEncoded
= *(BYTE
**)pbEncoded
;
1967 *pbEncoded
++ = ASN_INTEGER
;
1970 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1971 pbEncoded
+= lenBytes
;
1972 *pbEncoded
++ = padByte
;
1976 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1977 pbEncoded
+= lenBytes
;
1979 for (; significantBytes
> 0; significantBytes
--)
1980 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1984 __EXCEPT(page_fault
)
1986 SetLastError(STATUS_ACCESS_VIOLATION
);
1993 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1994 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1995 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2001 DWORD significantBytes
, lenBytes
;
2004 const CRYPT_INTEGER_BLOB
*blob
=
2005 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2007 significantBytes
= blob
->cbData
;
2008 if (significantBytes
)
2010 /* positive, lop off leading (little-endian) zeroes */
2011 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2014 if (significantBytes
== 0)
2015 significantBytes
= 1;
2016 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2020 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2022 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2023 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2028 *pcbEncoded
= bytesNeeded
;
2033 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2034 pcbEncoded
, bytesNeeded
)))
2036 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2037 pbEncoded
= *(BYTE
**)pbEncoded
;
2038 *pbEncoded
++ = ASN_INTEGER
;
2041 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2042 pbEncoded
+= lenBytes
;
2047 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2048 pbEncoded
+= lenBytes
;
2050 for (; significantBytes
> 0; significantBytes
--)
2051 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2055 __EXCEPT(page_fault
)
2057 SetLastError(STATUS_ACCESS_VIOLATION
);
2064 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2065 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2066 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2068 CRYPT_INTEGER_BLOB blob
;
2071 /* Encode as an unsigned integer, then change the tag to enumerated */
2072 blob
.cbData
= sizeof(DWORD
);
2073 blob
.pbData
= (BYTE
*)pvStructInfo
;
2074 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2075 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2076 if (ret
&& pbEncoded
)
2078 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2079 pbEncoded
= *(BYTE
**)pbEncoded
;
2080 pbEncoded
[0] = ASN_ENUMERATED
;
2085 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2086 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2087 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2094 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2095 * temporary buffer because the output buffer is not NULL-terminated.
2098 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2102 *pcbEncoded
= bytesNeeded
;
2107 /* Sanity check the year, this is a two-digit year format */
2108 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2110 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2112 SetLastError(CRYPT_E_BAD_ENCODE
);
2117 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2118 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2120 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2121 pbEncoded
= *(BYTE
**)pbEncoded
;
2122 buf
[0] = ASN_UTCTIME
;
2123 buf
[1] = bytesNeeded
- 2;
2124 snprintf(buf
+ 2, sizeof(buf
) - 2,
2125 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2126 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2127 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2128 sysTime
.wMinute
, sysTime
.wSecond
);
2129 memcpy(pbEncoded
, buf
, bytesNeeded
);
2134 __EXCEPT(page_fault
)
2136 SetLastError(STATUS_ACCESS_VIOLATION
);
2143 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2144 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2145 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2152 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2153 * temporary buffer because the output buffer is not NULL-terminated.
2156 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2160 *pcbEncoded
= bytesNeeded
;
2165 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2168 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2169 pcbEncoded
, bytesNeeded
);
2172 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2173 pbEncoded
= *(BYTE
**)pbEncoded
;
2174 buf
[0] = ASN_GENERALTIME
;
2175 buf
[1] = bytesNeeded
- 2;
2176 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2177 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2178 sysTime
.wMinute
, sysTime
.wSecond
);
2179 memcpy(pbEncoded
, buf
, bytesNeeded
);
2183 __EXCEPT(page_fault
)
2185 SetLastError(STATUS_ACCESS_VIOLATION
);
2192 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2193 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2194 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2202 /* Check the year, if it's in the UTCTime range call that encode func */
2203 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2205 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2206 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2207 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2209 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2210 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2213 __EXCEPT(page_fault
)
2215 SetLastError(STATUS_ACCESS_VIOLATION
);
2222 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2223 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2224 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2230 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2231 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2232 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2234 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2235 dataLen
+= seq
->rgValue
[i
].cbData
;
2236 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2237 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2240 *pcbEncoded
= bytesNeeded
;
2245 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2246 pcbEncoded
, bytesNeeded
)))
2248 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2249 pbEncoded
= *(BYTE
**)pbEncoded
;
2250 *pbEncoded
++ = ASN_SEQUENCEOF
;
2251 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2252 pbEncoded
+= lenBytes
;
2253 for (i
= 0; i
< seq
->cValue
; i
++)
2255 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2256 seq
->rgValue
[i
].cbData
);
2257 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2262 __EXCEPT(page_fault
)
2264 SetLastError(STATUS_ACCESS_VIOLATION
);
2271 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2272 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2273 void *pvEncoded
, DWORD
*pcbEncoded
)
2277 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2279 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2280 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2281 pvEncoded
, pcbEncoded
);
2283 if (!pvEncoded
&& !pcbEncoded
)
2285 SetLastError(ERROR_INVALID_PARAMETER
);
2288 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2289 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2291 SetLastError(ERROR_FILE_NOT_FOUND
);
2295 SetLastError(NOERROR
);
2296 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2297 *(BYTE
**)pvEncoded
= NULL
;
2298 if (!HIWORD(lpszStructType
))
2300 switch (LOWORD(lpszStructType
))
2302 case (WORD
)X509_CERT
:
2303 encodeFunc
= CRYPT_AsnEncodeCert
;
2305 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2306 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2308 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2309 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2311 case (WORD
)X509_EXTENSIONS
:
2312 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2314 case (WORD
)X509_NAME
:
2315 encodeFunc
= CRYPT_AsnEncodeName
;
2317 case (WORD
)X509_PUBLIC_KEY_INFO
:
2318 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2320 case (WORD
)X509_ALTERNATE_NAME
:
2321 encodeFunc
= CRYPT_AsnEncodeAltName
;
2323 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2324 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2326 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2327 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2329 case (WORD
)X509_OCTET_STRING
:
2330 encodeFunc
= CRYPT_AsnEncodeOctets
;
2332 case (WORD
)X509_BITS
:
2333 case (WORD
)X509_KEY_USAGE
:
2334 encodeFunc
= CRYPT_AsnEncodeBits
;
2336 case (WORD
)X509_INTEGER
:
2337 encodeFunc
= CRYPT_AsnEncodeInt
;
2339 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2340 encodeFunc
= CRYPT_AsnEncodeInteger
;
2342 case (WORD
)X509_MULTI_BYTE_UINT
:
2343 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2345 case (WORD
)X509_ENUMERATED
:
2346 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2348 case (WORD
)X509_CHOICE_OF_TIME
:
2349 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2351 case (WORD
)X509_SEQUENCE_OF_ANY
:
2352 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2354 case (WORD
)PKCS_UTC_TIME
:
2355 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2358 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2361 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2362 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2363 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2364 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2365 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2366 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2367 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2368 encodeFunc
= CRYPT_AsnEncodeBits
;
2369 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2370 encodeFunc
= CRYPT_AsnEncodeOctets
;
2371 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2372 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2373 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2374 encodeFunc
= CRYPT_AsnEncodeAltName
;
2375 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2376 encodeFunc
= CRYPT_AsnEncodeAltName
;
2377 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2378 encodeFunc
= CRYPT_AsnEncodeAltName
;
2379 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2380 encodeFunc
= CRYPT_AsnEncodeAltName
;
2381 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2382 encodeFunc
= CRYPT_AsnEncodeAltName
;
2384 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2385 debugstr_a(lpszStructType
));
2387 encodeFunc
= (CryptEncodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2388 lpszStructType
, "CryptEncodeObjectEx", &lib
);
2390 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2391 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2393 SetLastError(ERROR_FILE_NOT_FOUND
);
2399 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2400 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2401 DWORD
*pcbStructInfo
)
2405 CryptDecodeObjectFunc pCryptDecodeObject
;
2407 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2408 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2409 pvStructInfo
, pcbStructInfo
);
2411 if (!pvStructInfo
&& !pcbStructInfo
)
2413 SetLastError(ERROR_INVALID_PARAMETER
);
2417 /* Try registered DLL first.. */
2418 pCryptDecodeObject
=
2419 (CryptDecodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2420 lpszStructType
, "CryptDecodeObject", &lib
);
2421 if (pCryptDecodeObject
)
2423 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2424 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2429 /* If not, use CryptDecodeObjectEx */
2430 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2431 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2436 /* Gets the number of length bytes from the given (leading) length byte */
2437 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2439 /* Helper function to get the encoded length of the data starting at pbEncoded,
2440 * where pbEncoded[0] is the tag. If the data are too short to contain a
2441 * length or if the length is too large for cbEncoded, sets an appropriate
2442 * error code and returns FALSE.
2444 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2451 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2454 else if (pbEncoded
[1] <= 0x7f)
2456 if (pbEncoded
[1] + 1 > cbEncoded
)
2458 SetLastError(CRYPT_E_ASN1_EOD
);
2463 *len
= pbEncoded
[1];
2469 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2471 if (lenLen
> sizeof(DWORD
) + 1)
2473 SetLastError(CRYPT_E_ASN1_LARGE
);
2476 else if (lenLen
+ 2 > cbEncoded
)
2478 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2489 out
|= *pbEncoded
++;
2491 if (out
+ lenLen
+ 1 > cbEncoded
)
2493 SetLastError(CRYPT_E_ASN1_EOD
);
2506 /* Helper function to check *pcbStructInfo, set it to the required size, and
2507 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2508 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2509 * pointer to the newly allocated memory.
2511 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2512 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2517 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2519 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2520 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2522 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2523 if (!*(BYTE
**)pvStructInfo
)
2526 *pcbStructInfo
= bytesNeeded
;
2528 else if (*pcbStructInfo
< bytesNeeded
)
2530 *pcbStructInfo
= bytesNeeded
;
2531 SetLastError(ERROR_MORE_DATA
);
2537 /* A few of the members need explanation:
2539 * A sequence is decoded into a struct. The offset member is the
2540 * offset of this item within that struct.
2542 * The decoder function to use. If this is NULL, then the member isn't
2543 * decoded, but minSize space is reserved for it.
2545 * The minimum amount of space occupied after decoding. You must set this.
2547 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2548 * minSize space is filled with 0 for this member. (Any other failure
2549 * results in CRYPT_AsnDecodeSequence failing.)
2550 * hasPointer, pointerOffset, minSize:
2551 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2552 * the offset within the (outer) struct of the data pointer (or to the
2553 * first data pointer, if more than one exist).
2555 * Used by CRYPT_AsnDecodeSequence, not for your use.
2557 struct AsnDecodeSequenceItem
2560 CryptDecodeObjectExFunc decodeFunc
;
2564 DWORD pointerOffset
;
2568 /* This decodes an arbitrary sequence into a contiguous block of memory
2569 * (basically, a struct.) Each element being decoded is described by a struct
2570 * AsnDecodeSequenceItem, see above.
2571 * startingPointer is an optional pointer to the first place where dynamic
2572 * data will be stored. If you know the starting offset, you may pass it
2573 * here. Otherwise, pass NULL, and one will be inferred from the items.
2574 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2575 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2577 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2578 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2579 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2580 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2584 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
2585 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2588 if (pbEncoded
[0] == ASN_SEQUENCE
)
2592 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2594 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2595 DWORD i
, bytesNeeded
= 0, minSize
= 0;
2598 ptr
= pbEncoded
+ 1 + lenBytes
;
2599 for (i
= 0; ret
&& i
< cItem
; i
++)
2603 minSize
+= items
[i
].minSize
;
2604 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2606 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2609 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2611 if (items
[i
].decodeFunc
)
2613 TRACE("sizing item %ld\n", i
);
2614 ret
= items
[i
].decodeFunc(dwCertEncodingType
, NULL
,
2615 ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2616 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2620 /* Account for alignment padding */
2621 bytesNeeded
+= items
[i
].size
;
2622 if (items
[i
].size
% sizeof(DWORD
))
2623 bytesNeeded
+= sizeof(DWORD
) -
2624 items
[i
].size
% sizeof(DWORD
);
2625 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2627 else if (items
[i
].optional
&&
2628 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2630 TRACE("skipping optional item %ld\n", i
);
2631 bytesNeeded
+= items
[i
].minSize
;
2632 SetLastError(NOERROR
);
2636 TRACE("item %ld failed: %08lx\n", i
,
2640 bytesNeeded
+= items
[i
].minSize
;
2643 else if (items
[i
].optional
)
2644 bytesNeeded
+= items
[i
].minSize
;
2647 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2651 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2653 TRACE("%ld remaining bytes, failing\n", cbEncoded
-
2655 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2661 *pcbStructInfo
= bytesNeeded
;
2662 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2663 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2667 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2668 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2669 if (startingPointer
)
2670 nextData
= (BYTE
*)startingPointer
;
2672 nextData
= (BYTE
*)pvStructInfo
+ minSize
;
2673 memset(pvStructInfo
, 0, minSize
);
2674 ptr
= pbEncoded
+ 1 + lenBytes
;
2675 for (i
= 0; ret
&& i
< cItem
; i
++)
2677 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2680 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2682 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2684 if (items
[i
].hasPointer
)
2686 *(BYTE
**)((BYTE
*)pvStructInfo
+
2687 items
[i
].pointerOffset
) = nextData
;
2689 if (items
[i
].decodeFunc
)
2691 TRACE("decoding item %ld\n", i
);
2692 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2693 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2694 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2695 (BYTE
*)pvStructInfo
+ items
[i
].offset
,
2698 TRACE("item %ld failed: %08lx\n", i
,
2702 items
[i
].size
= items
[i
].minSize
;
2705 if (items
[i
].hasPointer
&&
2706 items
[i
].size
> items
[i
].minSize
)
2708 nextData
+= items
[i
].size
-
2710 /* align nextData to DWORD boundaries */
2711 if (items
[i
].size
% sizeof(DWORD
))
2713 nextData
+= sizeof(DWORD
) -
2714 items
[i
].size
% sizeof(DWORD
);
2717 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2719 else if (items
[i
].optional
&&
2720 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2722 SetLastError(NOERROR
);
2726 else if (!items
[i
].optional
)
2728 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2738 SetLastError(CRYPT_E_ASN1_BADTAG
);
2741 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2745 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2746 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2747 * to CRYPT_E_ASN1_CORRUPT.
2748 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2751 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2752 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2753 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2758 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2760 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2761 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2763 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2764 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2767 *pcbStructInfo
= bytesNeeded
;
2768 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2769 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2771 CRYPT_DER_BLOB
*blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
2773 blob
->cbData
= 1 + lenBytes
+ dataLen
;
2776 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2777 blob
->pbData
= (BYTE
*)pbEncoded
;
2780 assert(blob
->pbData
);
2781 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
2786 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2794 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2795 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
2796 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2797 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2801 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
2802 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2804 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2807 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
2808 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
2809 pvStructInfo
, pcbStructInfo
);
2810 if (ret
&& pvStructInfo
)
2812 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2819 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2821 temp
= blob
->pbData
[i
];
2822 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2823 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2827 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2831 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
2832 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2833 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2837 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2838 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2842 struct AsnDecodeSequenceItem items
[] = {
2843 { offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
2844 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2845 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
2846 { offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
),
2847 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2848 FALSE
, TRUE
, offsetof(CERT_SIGNED_CONTENT_INFO
,
2849 SignatureAlgorithm
.pszObjId
), 0 },
2850 { offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
2851 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2852 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
2855 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
2856 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
2857 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2858 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2859 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2861 __EXCEPT(page_fault
)
2863 SetLastError(STATUS_ACCESS_VIOLATION
);
2870 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
2871 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2872 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2876 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
))
2880 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2882 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2884 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2885 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
2886 pvStructInfo
, pcbStructInfo
);
2891 SetLastError(CRYPT_E_ASN1_BADTAG
);
2897 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
2898 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2899 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2903 struct AsnDecodeSequenceItem items
[] = {
2904 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
2905 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2906 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
2907 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2910 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2911 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2912 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2916 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
2917 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2918 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2922 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3))
2926 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2928 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2930 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
2931 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
2932 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2937 SetLastError(CRYPT_E_ASN1_BADTAG
);
2943 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
2944 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2945 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2949 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2950 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2954 struct AsnDecodeSequenceItem items
[] = {
2955 { offsetof(CERT_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
2956 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
2957 { offsetof(CERT_INFO
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2958 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2959 SerialNumber
.pbData
), 0 },
2960 { offsetof(CERT_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
2961 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2962 SignatureAlgorithm
.pszObjId
), 0 },
2963 { offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
2964 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2966 { offsetof(CERT_INFO
, NotBefore
), CRYPT_AsnDecodeValidity
,
2967 sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
, FALSE
, 0 },
2968 { offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
2969 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2971 { offsetof(CERT_INFO
, SubjectPublicKeyInfo
), CRYPT_AsnDecodePubKeyInfo
,
2972 sizeof(CERT_PUBLIC_KEY_INFO
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2973 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
2974 { offsetof(CERT_INFO
, IssuerUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2975 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2976 IssuerUniqueId
.pbData
), 0 },
2977 { offsetof(CERT_INFO
, SubjectUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2978 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2979 SubjectUniqueId
.pbData
), 0 },
2980 { offsetof(CERT_INFO
, cExtension
), CRYPT_AsnDecodeCertExtensions
,
2981 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2985 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2986 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2987 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2989 __EXCEPT(page_fault
)
2991 SetLastError(STATUS_ACCESS_VIOLATION
);
2998 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2999 DWORD dwFlags
, PCRL_ENTRY entry
, DWORD
*pcbEntry
)
3002 struct AsnDecodeSequenceItem items
[] = {
3003 { offsetof(CRL_ENTRY
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
3004 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CRL_ENTRY
,
3005 SerialNumber
.pbData
), 0 },
3006 { offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
3007 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3008 { offsetof(CRL_ENTRY
, cExtension
), CRYPT_AsnDecodeExtensionsInternal
,
3009 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CRL_ENTRY
,
3013 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
3016 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3017 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3018 NULL
, entry
, pcbEntry
, entry
? entry
->SerialNumber
.pbData
: NULL
);
3019 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3023 typedef struct _WINE_CRL_ENTRIES
{
3025 PCRL_ENTRY rgCRLEntry
;
3026 } WINE_CRL_ENTRIES
, *PWINE_CRL_ENTRIES
;
3028 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
3029 * been set prior to calling.
3031 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
3032 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3033 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3037 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3038 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3040 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3042 DWORD dataLen
, bytesNeeded
;
3044 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3046 DWORD cCRLEntry
= 0;
3047 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3049 bytesNeeded
= sizeof(WINE_CRL_ENTRIES
);
3055 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3056 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3059 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3060 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3066 bytesNeeded
+= size
;
3067 ret
= CRYPT_GetLen(ptr
,
3068 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3070 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3077 *pcbStructInfo
= bytesNeeded
;
3078 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3079 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3084 PWINE_CRL_ENTRIES entries
;
3086 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3087 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3088 *pcbStructInfo
= bytesNeeded
;
3089 entries
= (PWINE_CRL_ENTRIES
)pvStructInfo
;
3090 entries
->cCRLEntry
= cCRLEntry
;
3091 assert(entries
->rgCRLEntry
);
3092 nextData
= (BYTE
*)entries
->rgCRLEntry
+
3093 entries
->cCRLEntry
* sizeof(CRL_ENTRY
);
3094 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3095 i
< cCRLEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
3098 entries
->rgCRLEntry
[i
].SerialNumber
.pbData
= nextData
;
3100 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3101 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3102 &entries
->rgCRLEntry
[i
], &size
);
3107 bytesNeeded
-= size
;
3108 /* Increment nextData by the difference of the
3109 * minimum size and the actual size.
3111 if (size
> sizeof(CRL_ENTRY
))
3112 nextData
+= size
- sizeof(CRL_ENTRY
);
3113 ret
= CRYPT_GetLen(ptr
,
3114 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3116 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3125 SetLastError(CRYPT_E_ASN1_BADTAG
);
3128 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3132 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
3133 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3134 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3138 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3139 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3143 struct AsnDecodeSequenceItem items
[] = {
3144 { offsetof(CRL_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
3145 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3146 { offsetof(CRL_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
3147 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3148 SignatureAlgorithm
.pszObjId
), 0 },
3149 { offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3150 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3152 { offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3153 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3154 { offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3155 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
3156 { offsetof(CRL_INFO
, cCRLEntry
), CRYPT_AsnDecodeCRLEntries
,
3157 sizeof(WINE_CRL_ENTRIES
), TRUE
, TRUE
, offsetof(CRL_INFO
,
3159 /* Note that the extensions are ignored by MS, so I'll ignore them too
3161 { offsetof(CRL_INFO
, cExtension
), NULL
,
3162 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
3165 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3166 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3167 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3169 __EXCEPT(page_fault
)
3171 SetLastError(STATUS_ACCESS_VIOLATION
);
3176 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3180 /* Differences between this and CRYPT_AsnDecodeOid:
3181 * - pvStructInfo is a LPSTR *, not an LPSTR
3182 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3183 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3186 static BOOL WINAPI
CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType
,
3187 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3188 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3192 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3193 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3195 ret
= CRYPT_AsnDecodeOid(pbEncoded
, cbEncoded
, dwFlags
,
3196 pvStructInfo
? *(LPSTR
*)pvStructInfo
: NULL
, pcbStructInfo
);
3197 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
3198 *pcbStructInfo
+= sizeof(LPSTR
);
3199 if (ret
&& pvStructInfo
)
3200 TRACE("returning %s\n", debugstr_a(*(LPSTR
*)pvStructInfo
));
3204 /* Warning: assumes ext->pszObjId is set ahead of time! */
3205 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3206 DWORD dwFlags
, CERT_EXTENSION
*ext
, DWORD
*pcbExt
)
3208 struct AsnDecodeSequenceItem items
[] = {
3209 { offsetof(CERT_EXTENSION
, pszObjId
), CRYPT_AsnDecodeOidWrapper
,
3210 sizeof(LPSTR
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
, pszObjId
), 0 },
3211 { offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
3212 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
3213 { offsetof(CERT_EXTENSION
, Value
), CRYPT_AsnDecodeOctetsInternal
,
3214 sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
,
3219 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
3223 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
3224 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3225 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3226 ext
, pcbExt
, ext
? ext
->pszObjId
: NULL
);
3228 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
3229 debugstr_a(ext
->pszObjId
));
3230 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3234 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
3235 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3236 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3240 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3241 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3243 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3245 DWORD dataLen
, bytesNeeded
;
3247 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3249 DWORD cExtension
= 0;
3250 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3252 bytesNeeded
= sizeof(CERT_EXTENSIONS
);
3258 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3259 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3262 ret
= CRYPT_AsnDecodeExtension(ptr
,
3263 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3269 bytesNeeded
+= size
;
3270 ret
= CRYPT_GetLen(ptr
,
3271 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3273 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3280 *pcbStructInfo
= bytesNeeded
;
3281 else if (*pcbStructInfo
< bytesNeeded
)
3283 SetLastError(ERROR_MORE_DATA
);
3284 *pcbStructInfo
= bytesNeeded
;
3292 CERT_EXTENSIONS
*exts
;
3294 *pcbStructInfo
= bytesNeeded
;
3295 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3296 exts
->cExtension
= cExtension
;
3297 assert(exts
->rgExtension
);
3298 nextData
= (BYTE
*)exts
->rgExtension
+
3299 exts
->cExtension
* sizeof(CERT_EXTENSION
);
3300 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3301 i
< cExtension
&& ptr
- pbEncoded
- 1 - lenBytes
<
3304 exts
->rgExtension
[i
].pszObjId
= (LPSTR
)nextData
;
3306 ret
= CRYPT_AsnDecodeExtension(ptr
,
3307 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3308 &exts
->rgExtension
[i
], &size
);
3313 bytesNeeded
-= size
;
3314 if (size
> sizeof(CERT_EXTENSION
))
3315 nextData
+= size
- sizeof(CERT_EXTENSION
);
3316 ret
= CRYPT_GetLen(ptr
,
3317 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3319 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3328 SetLastError(CRYPT_E_ASN1_BADTAG
);
3334 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3335 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3336 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3342 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3343 lpszStructType
, pbEncoded
, cbEncoded
,
3344 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3345 if (ret
&& pvStructInfo
)
3347 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3348 pcbStructInfo
, *pcbStructInfo
);
3351 CERT_EXTENSIONS
*exts
;
3353 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3354 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3355 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3356 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3357 sizeof(CERT_EXTENSIONS
));
3358 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3359 lpszStructType
, pbEncoded
, cbEncoded
,
3360 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3365 __EXCEPT(page_fault
)
3367 SetLastError(STATUS_ACCESS_VIOLATION
);
3374 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3375 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3376 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
)
3380 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, pszObjId
,
3385 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3389 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3391 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3396 /* The largest possible string for the first two components
3397 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3402 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3403 pbEncoded
[1 + lenBytes
] / 40,
3404 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3406 bytesNeeded
= strlen(firstTwo
) + 1;
3407 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3408 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3410 /* large enough for ".4000000" */
3414 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3421 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3424 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3431 snprintf(str
, sizeof(str
), ".%d", val
);
3432 bytesNeeded
+= strlen(str
);
3436 *pcbObjId
= bytesNeeded
;
3437 else if (*pcbObjId
< bytesNeeded
)
3439 *pcbObjId
= bytesNeeded
;
3440 SetLastError(ERROR_MORE_DATA
);
3446 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3447 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3449 pszObjId
+= strlen(pszObjId
);
3450 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3451 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3455 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3464 sprintf(pszObjId
, ".%d", val
);
3465 pszObjId
+= strlen(pszObjId
);
3471 *pcbObjId
= bytesNeeded
;
3476 SetLastError(CRYPT_E_ASN1_BADTAG
);
3480 __EXCEPT(page_fault
)
3482 SetLastError(STATUS_ACCESS_VIOLATION
);
3489 /* Warning: this assumes the address of value->Value.pbData is already set, in
3490 * order to avoid overwriting memory. (In some cases, it may change it, if it
3491 * doesn't copy anything to memory.) Be sure to set it correctly!
3493 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(const BYTE
*pbEncoded
,
3494 DWORD cbEncoded
, DWORD dwFlags
, CERT_NAME_VALUE
*value
, DWORD
*pcbValue
)
3502 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3504 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3506 switch (pbEncoded
[0])
3508 case ASN_NUMERICSTRING
:
3509 case ASN_PRINTABLESTRING
:
3513 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3514 SetLastError(OSS_UNIMPLEMENTED
);
3519 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3521 switch (pbEncoded
[0])
3523 case ASN_NUMERICSTRING
:
3524 case ASN_PRINTABLESTRING
:
3526 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3527 bytesNeeded
+= dataLen
;
3531 *pcbValue
= bytesNeeded
;
3532 else if (*pcbValue
< bytesNeeded
)
3534 *pcbValue
= bytesNeeded
;
3535 SetLastError(ERROR_MORE_DATA
);
3540 *pcbValue
= bytesNeeded
;
3541 switch (pbEncoded
[0])
3543 case ASN_NUMERICSTRING
:
3544 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3546 case ASN_PRINTABLESTRING
:
3547 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3550 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3555 switch (pbEncoded
[0])
3557 case ASN_NUMERICSTRING
:
3558 case ASN_PRINTABLESTRING
:
3560 value
->Value
.cbData
= dataLen
;
3561 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3562 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3566 assert(value
->Value
.pbData
);
3567 memcpy(value
->Value
.pbData
,
3568 pbEncoded
+ 1 + lenBytes
, dataLen
);
3575 value
->Value
.cbData
= 0;
3576 value
->Value
.pbData
= NULL
;
3582 __EXCEPT(page_fault
)
3584 SetLastError(STATUS_ACCESS_VIOLATION
);
3591 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3592 * at the moment because of the ASN_CONSTRUCTOR tag.)
3594 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
,
3595 DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN_ATTR
*attr
, DWORD
*pcbAttr
)
3601 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
3603 DWORD bytesNeeded
, dataLen
, size
;
3606 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3608 /* The data length must be at least 4, two for the tag and
3609 * length for the OID, and two for the string (assuming both
3610 * have short-form lengths.)
3614 SetLastError(CRYPT_E_ASN1_EOD
);
3619 bytesNeeded
= sizeof(CERT_RDN_ATTR
);
3620 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3621 ret
= CRYPT_AsnDecodeOid(pbEncoded
+ 1 + lenBytes
,
3622 cbEncoded
- 1 - lenBytes
, dwFlags
, NULL
, &size
);
3625 /* ugly: need to know the size of the next element of
3626 * the sequence, so get it directly
3628 DWORD objIdOfset
= 1 + lenBytes
, objIdLen
,
3629 nameValueOffset
= 0;
3631 ret
= CRYPT_GetLen(pbEncoded
+ objIdOfset
,
3632 cbEncoded
- objIdOfset
, &objIdLen
);
3633 bytesNeeded
+= size
;
3634 /* hack: like encoding, this takes advantage of the
3635 * fact that the rest of the structure is identical to
3636 * a CERT_NAME_VALUE.
3640 nameValueOffset
= objIdOfset
+ objIdLen
+ 1 +
3641 GET_LEN_BYTES(pbEncoded
[objIdOfset
]);
3642 ret
= CRYPT_AsnDecodeNameValue(
3643 pbEncoded
+ nameValueOffset
,
3644 cbEncoded
- nameValueOffset
, dwFlags
, NULL
, &size
);
3648 bytesNeeded
+= size
;
3650 *pcbAttr
= bytesNeeded
;
3651 else if (*pcbAttr
< bytesNeeded
)
3653 *pcbAttr
= bytesNeeded
;
3654 SetLastError(ERROR_MORE_DATA
);
3659 BYTE
*originalData
= attr
->Value
.pbData
;
3661 *pcbAttr
= bytesNeeded
;
3662 /* strange: decode the value first, because it
3663 * has a counted size, and we can store the OID
3664 * after it. Keep track of the original data
3665 * pointer, we'll need to know whether it was
3669 ret
= CRYPT_AsnDecodeNameValue(
3670 pbEncoded
+ nameValueOffset
,
3671 cbEncoded
- nameValueOffset
, dwFlags
,
3672 (CERT_NAME_VALUE
*)&attr
->dwValueType
, &size
);
3677 /* if the data were copied to the
3678 * original location, the OID goes
3679 * after. Otherwise it goes in the
3680 * spot originally reserved for the
3683 if (attr
->Value
.pbData
== originalData
)
3685 (LPSTR
)(attr
->Value
.pbData
+
3686 attr
->Value
.cbData
);
3689 (LPSTR
)originalData
;
3690 size
= bytesNeeded
- size
;
3691 ret
= CRYPT_AsnDecodeOid(
3692 pbEncoded
+ objIdOfset
,
3693 cbEncoded
- objIdOfset
,
3694 dwFlags
, attr
->pszObjId
, &size
);
3697 attr
->pszObjId
= NULL
;
3707 SetLastError(CRYPT_E_ASN1_BADTAG
);
3711 __EXCEPT(page_fault
)
3713 SetLastError(STATUS_ACCESS_VIOLATION
);
3720 static BOOL WINAPI
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3721 DWORD dwFlags
, CERT_RDN
*rdn
, DWORD
*pcbRdn
)
3727 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SETOF
))
3731 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3733 DWORD bytesNeeded
, cRDNAttr
= 0;
3734 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3736 bytesNeeded
= sizeof(CERT_RDN
);
3742 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3743 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3745 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3746 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3752 bytesNeeded
+= size
;
3753 ret
= CRYPT_GetLen(ptr
,
3754 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3756 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3763 *pcbRdn
= bytesNeeded
;
3764 else if (*pcbRdn
< bytesNeeded
)
3766 *pcbRdn
= bytesNeeded
;
3767 SetLastError(ERROR_MORE_DATA
);
3776 *pcbRdn
= bytesNeeded
;
3777 rdn
->cRDNAttr
= cRDNAttr
;
3778 rdn
->rgRDNAttr
= (CERT_RDN_ATTR
*)((BYTE
*)rdn
+
3780 nextData
= (BYTE
*)rdn
->rgRDNAttr
+
3781 rdn
->cRDNAttr
* sizeof(CERT_RDN_ATTR
);
3782 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3783 i
< cRDNAttr
&& ptr
- pbEncoded
- 1 - lenBytes
<
3786 rdn
->rgRDNAttr
[i
].Value
.pbData
= nextData
;
3788 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3789 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3790 &rdn
->rgRDNAttr
[i
], &size
);
3795 bytesNeeded
-= size
;
3796 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3797 * data may not have been copied.
3799 if (rdn
->rgRDNAttr
[i
].Value
.pbData
== nextData
)
3801 rdn
->rgRDNAttr
[i
].Value
.cbData
;
3802 /* Ugly: the OID, if copied, is stored in
3803 * memory after the value, so increment by its
3804 * string length if it's set and points here.
3806 if ((const BYTE
*)rdn
->rgRDNAttr
[i
].pszObjId
3809 rdn
->rgRDNAttr
[i
].pszObjId
) + 1;
3810 ret
= CRYPT_GetLen(ptr
,
3811 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3813 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3822 SetLastError(CRYPT_E_ASN1_BADTAG
);
3826 __EXCEPT(page_fault
)
3828 SetLastError(STATUS_ACCESS_VIOLATION
);
3835 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3836 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3837 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3843 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCEOF
))
3847 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3849 DWORD bytesNeeded
, cRDN
= 0;
3850 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3852 bytesNeeded
= sizeof(CERT_NAME_INFO
);
3857 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3858 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3862 ret
= CRYPT_AsnDecodeRdn(ptr
,
3863 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3869 bytesNeeded
+= size
;
3870 ret
= CRYPT_GetLen(ptr
,
3871 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3873 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3880 *pcbStructInfo
= bytesNeeded
;
3881 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3882 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3884 CERT_NAME_INFO
*info
;
3886 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3887 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3888 info
= (CERT_NAME_INFO
*)pvStructInfo
;
3890 if (info
->cRDN
== 0)
3898 info
->rgRDN
= (CERT_RDN
*)((BYTE
*)pvStructInfo
+
3899 sizeof(CERT_NAME_INFO
));
3900 nextData
= (BYTE
*)info
->rgRDN
+
3901 info
->cRDN
* sizeof(CERT_RDN
);
3902 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3903 i
< cRDN
&& ptr
- pbEncoded
- 1 - lenBytes
<
3906 info
->rgRDN
[i
].rgRDNAttr
=
3907 (CERT_RDN_ATTR
*)nextData
;
3909 ret
= CRYPT_AsnDecodeRdn(ptr
,
3910 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3911 &info
->rgRDN
[i
], &size
);
3917 bytesNeeded
-= size
;
3918 ret
= CRYPT_GetLen(ptr
,
3919 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3921 ptr
+= nextLen
+ 1 +
3922 GET_LEN_BYTES(ptr
[1]);
3932 SetLastError(CRYPT_E_ASN1_BADTAG
);
3936 __EXCEPT(page_fault
)
3938 SetLastError(STATUS_ACCESS_VIOLATION
);
3945 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
3946 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3947 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3950 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
3952 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3953 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3955 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3956 bytesNeeded
+= cbEncoded
;
3958 *pcbStructInfo
= bytesNeeded
;
3959 else if (*pcbStructInfo
< bytesNeeded
)
3961 SetLastError(ERROR_MORE_DATA
);
3962 *pcbStructInfo
= bytesNeeded
;
3967 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
3969 *pcbStructInfo
= bytesNeeded
;
3970 blob
->cbData
= cbEncoded
;
3971 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3972 blob
->pbData
= (LPBYTE
)pbEncoded
;
3975 assert(blob
->pbData
);
3976 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3982 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3983 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3984 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3986 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3987 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3989 struct AsnDecodeSequenceItem items
[] = {
3990 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
3991 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3992 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
3993 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
3994 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
3995 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
3998 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3999 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4001 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4002 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4003 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
4004 if (ret
&& pvStructInfo
)
4006 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
4007 debugstr_a(algo
->pszObjId
));
4012 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
4013 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4014 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4020 struct AsnDecodeSequenceItem items
[] = {
4021 { offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
4022 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
4023 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
4024 Algorithm
.pszObjId
) },
4025 { offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
4026 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
4027 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
4030 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4031 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4032 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4034 __EXCEPT(page_fault
)
4036 SetLastError(STATUS_ACCESS_VIOLATION
);
4043 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
4044 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4045 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4051 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4054 if (pbEncoded
[0] != ASN_BOOL
)
4056 SetLastError(CRYPT_E_ASN1_BADTAG
);
4059 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
4061 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4064 if (pbEncoded
[1] > 1)
4066 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4071 *pcbStructInfo
= sizeof(BOOL
);
4074 else if (*pcbStructInfo
< sizeof(BOOL
))
4076 *pcbStructInfo
= sizeof(BOOL
);
4077 SetLastError(ERROR_MORE_DATA
);
4082 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
4085 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4089 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4090 DWORD dwFlags
, CERT_ALT_NAME_ENTRY
*entry
, DWORD
*pcbEntry
)
4092 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
4097 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4100 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
4102 SetLastError(CRYPT_E_ASN1_BADTAG
);
4105 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4106 if (1 + lenBytes
> cbEncoded
)
4108 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4111 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4113 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4115 case 1: /* rfc822Name */
4116 case 2: /* dNSName */
4117 case 6: /* uniformResourceIdentifier */
4118 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
4120 case 7: /* iPAddress */
4121 bytesNeeded
+= dataLen
;
4123 case 8: /* registeredID */
4124 /* FIXME: decode as OID */
4125 case 0: /* otherName */
4126 case 4: /* directoryName */
4128 SetLastError(CRYPT_E_ASN1_BADTAG
);
4131 case 3: /* x400Address, unimplemented */
4132 case 5: /* ediPartyName, unimplemented */
4133 SetLastError(CRYPT_E_ASN1_BADTAG
);
4137 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4143 *pcbEntry
= bytesNeeded
;
4144 else if (*pcbEntry
< bytesNeeded
)
4146 SetLastError(ERROR_MORE_DATA
);
4151 /* MS used values one greater than the asn1 ones.. sigh */
4152 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
4153 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4155 case 1: /* rfc822Name */
4156 case 2: /* dNSName */
4157 case 6: /* uniformResourceIdentifier */
4161 for (i
= 0; i
< dataLen
; i
++)
4162 entry
->u
.pwszURL
[i
] =
4163 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
4164 entry
->u
.pwszURL
[i
] = 0;
4167 case 7: /* iPAddress */
4168 /* The next data pointer is in the pwszURL spot, that is,
4169 * the first 4 bytes. Need to move it to the next spot.
4171 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
4172 entry
->u
.IPAddress
.cbData
= dataLen
;
4173 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
4183 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
4184 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4185 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4191 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
4195 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4197 DWORD bytesNeeded
, cEntry
= 0;
4198 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4200 bytesNeeded
= sizeof(CERT_ALT_NAME_INFO
);
4205 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4206 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
4210 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4211 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
4217 bytesNeeded
+= size
;
4218 ret
= CRYPT_GetLen(ptr
,
4219 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4221 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
4228 *pcbStructInfo
= bytesNeeded
;
4229 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4230 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4232 CERT_ALT_NAME_INFO
*info
;
4234 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4235 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4236 info
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
4237 info
->cAltEntry
= 0;
4239 info
->rgAltEntry
= NULL
;
4247 (CERT_ALT_NAME_ENTRY
*)((BYTE
*)pvStructInfo
+
4248 sizeof(CERT_ALT_NAME_INFO
));
4249 nextData
= (BYTE
*)info
->rgAltEntry
+
4250 cEntry
* sizeof(CERT_ALT_NAME_ENTRY
);
4251 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4252 i
< cEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
4255 info
->rgAltEntry
[i
].u
.pwszURL
=
4258 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4259 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
4260 &info
->rgAltEntry
[i
], &size
);
4267 sizeof(CERT_ALT_NAME_ENTRY
);
4268 bytesNeeded
-= size
;
4269 ret
= CRYPT_GetLen(ptr
,
4270 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4272 ptr
+= nextLen
+ 1 +
4273 GET_LEN_BYTES(ptr
[1]);
4283 SetLastError(CRYPT_E_ASN1_BADTAG
);
4287 __EXCEPT(page_fault
)
4289 SetLastError(STATUS_ACCESS_VIOLATION
);
4296 struct PATH_LEN_CONSTRAINT
4298 BOOL fPathLenConstraint
;
4299 DWORD dwPathLenConstraint
;
4302 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
4303 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4304 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4310 if (pbEncoded
[0] == ASN_INTEGER
)
4312 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
4315 *pcbStructInfo
= bytesNeeded
;
4316 else if (*pcbStructInfo
< bytesNeeded
)
4318 SetLastError(ERROR_MORE_DATA
);
4319 *pcbStructInfo
= bytesNeeded
;
4324 struct PATH_LEN_CONSTRAINT
*constraint
=
4325 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
4326 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
4328 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
4329 pbEncoded
, cbEncoded
, 0, NULL
,
4330 &constraint
->dwPathLenConstraint
, &size
);
4332 constraint
->fPathLenConstraint
= TRUE
;
4333 TRACE("got an int, dwPathLenConstraint is %ld\n",
4334 constraint
->dwPathLenConstraint
);
4339 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4343 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4347 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
4348 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4349 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4355 struct AsnDecodeSequenceItem items
[] = {
4356 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
), CRYPT_AsnDecodeBool
,
4357 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
4358 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fPathLenConstraint
),
4359 CRYPT_AsnDecodePathLenConstraint
, sizeof(struct PATH_LEN_CONSTRAINT
),
4360 TRUE
, FALSE
, 0, 0 },
4363 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4364 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4365 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4367 __EXCEPT(page_fault
)
4369 SetLastError(STATUS_ACCESS_VIOLATION
);
4376 #define RSA1_MAGIC 0x31415352
4378 struct DECODED_RSA_PUB_KEY
4381 CRYPT_INTEGER_BLOB modulus
;
4384 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4385 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4386 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4392 struct AsnDecodeSequenceItem items
[] = {
4393 { offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4394 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4395 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4397 { offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4398 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4400 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4403 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4404 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4405 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4408 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4409 decodedKey
->modulus
.cbData
;
4413 *pcbStructInfo
= bytesNeeded
;
4416 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4417 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4420 RSAPUBKEY
*rsaPubKey
;
4422 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4423 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4424 hdr
= (BLOBHEADER
*)pvStructInfo
;
4425 hdr
->bType
= PUBLICKEYBLOB
;
4426 hdr
->bVersion
= CUR_BLOB_VERSION
;
4428 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4429 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4430 sizeof(BLOBHEADER
));
4431 rsaPubKey
->magic
= RSA1_MAGIC
;
4432 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4433 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4434 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4435 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4436 decodedKey
->modulus
.cbData
);
4438 LocalFree(decodedKey
);
4441 __EXCEPT(page_fault
)
4443 SetLastError(STATUS_ACCESS_VIOLATION
);
4450 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
4451 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4452 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4456 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4457 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4459 if (pbEncoded
[0] == ASN_OCTETSTRING
)
4461 DWORD bytesNeeded
, dataLen
;
4463 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4465 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4466 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4468 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4470 *pcbStructInfo
= bytesNeeded
;
4471 else if (*pcbStructInfo
< bytesNeeded
)
4473 SetLastError(ERROR_MORE_DATA
);
4474 *pcbStructInfo
= bytesNeeded
;
4479 CRYPT_DATA_BLOB
*blob
;
4480 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4482 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4483 blob
->cbData
= dataLen
;
4484 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4485 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4488 assert(blob
->pbData
);
4490 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4498 SetLastError(CRYPT_E_ASN1_BADTAG
);
4504 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4505 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4506 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4510 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4511 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4517 if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4518 lpszStructType
, pbEncoded
, cbEncoded
,
4519 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4522 *pcbStructInfo
= bytesNeeded
;
4523 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4524 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4526 CRYPT_DATA_BLOB
*blob
;
4528 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4529 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4530 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4531 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
4532 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4533 lpszStructType
, pbEncoded
, cbEncoded
,
4534 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4540 SetLastError(CRYPT_E_ASN1_BADTAG
);
4544 __EXCEPT(page_fault
)
4546 SetLastError(STATUS_ACCESS_VIOLATION
);
4553 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4554 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4555 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4559 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4560 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4562 if (pbEncoded
[0] == ASN_BITSTRING
)
4564 DWORD bytesNeeded
, dataLen
;
4566 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4568 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4569 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4571 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4573 *pcbStructInfo
= bytesNeeded
;
4574 else if (*pcbStructInfo
< bytesNeeded
)
4576 *pcbStructInfo
= bytesNeeded
;
4577 SetLastError(ERROR_MORE_DATA
);
4582 CRYPT_BIT_BLOB
*blob
;
4584 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4585 blob
->cbData
= dataLen
- 1;
4586 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4587 GET_LEN_BYTES(pbEncoded
[1]));
4588 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4590 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4591 GET_LEN_BYTES(pbEncoded
[1]);
4595 assert(blob
->pbData
);
4598 BYTE mask
= 0xff << blob
->cUnusedBits
;
4600 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4601 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4602 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4610 SetLastError(CRYPT_E_ASN1_BADTAG
);
4613 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4617 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4618 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4619 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4623 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4624 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4630 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4631 lpszStructType
, pbEncoded
, cbEncoded
,
4632 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4635 *pcbStructInfo
= bytesNeeded
;
4636 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4637 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4639 CRYPT_BIT_BLOB
*blob
;
4641 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4642 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4643 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4644 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4645 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4646 lpszStructType
, pbEncoded
, cbEncoded
,
4647 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4652 __EXCEPT(page_fault
)
4654 SetLastError(STATUS_ACCESS_VIOLATION
);
4658 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4662 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4663 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4664 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4670 *pcbStructInfo
= sizeof(int);
4675 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4676 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4677 DWORD size
= sizeof(buf
);
4679 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4680 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4681 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4684 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4685 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4689 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4690 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4691 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4693 /* initialize to a negative value to sign-extend */
4698 for (i
= 0; i
< blob
->cbData
; i
++)
4701 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4703 memcpy(pvStructInfo
, &val
, sizeof(int));
4706 else if (GetLastError() == ERROR_MORE_DATA
)
4707 SetLastError(CRYPT_E_ASN1_LARGE
);
4709 __EXCEPT(page_fault
)
4711 SetLastError(STATUS_ACCESS_VIOLATION
);
4718 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4719 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4720 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4724 if (pbEncoded
[0] == ASN_INTEGER
)
4726 DWORD bytesNeeded
, dataLen
;
4728 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4730 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4732 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4734 *pcbStructInfo
= bytesNeeded
;
4735 else if (*pcbStructInfo
< bytesNeeded
)
4737 *pcbStructInfo
= bytesNeeded
;
4738 SetLastError(ERROR_MORE_DATA
);
4743 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4745 blob
->cbData
= dataLen
;
4746 assert(blob
->pbData
);
4751 for (i
= 0; i
< blob
->cbData
; i
++)
4753 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4762 SetLastError(CRYPT_E_ASN1_BADTAG
);
4768 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4769 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4770 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4778 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4779 lpszStructType
, pbEncoded
, cbEncoded
,
4780 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4783 *pcbStructInfo
= bytesNeeded
;
4784 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4785 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4787 CRYPT_INTEGER_BLOB
*blob
;
4789 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4790 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4791 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4792 blob
->pbData
= (BYTE
*)pvStructInfo
+
4793 sizeof(CRYPT_INTEGER_BLOB
);
4794 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4795 lpszStructType
, pbEncoded
, cbEncoded
,
4796 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4801 __EXCEPT(page_fault
)
4803 SetLastError(STATUS_ACCESS_VIOLATION
);
4810 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
4811 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
4812 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4813 void *pvStructInfo
, DWORD
*pcbStructInfo
)
4817 if (pbEncoded
[0] == ASN_INTEGER
)
4819 DWORD bytesNeeded
, dataLen
;
4821 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4823 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4825 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4827 *pcbStructInfo
= bytesNeeded
;
4828 else if (*pcbStructInfo
< bytesNeeded
)
4830 *pcbStructInfo
= bytesNeeded
;
4831 SetLastError(ERROR_MORE_DATA
);
4836 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4838 blob
->cbData
= dataLen
;
4839 assert(blob
->pbData
);
4840 /* remove leading zero byte if it exists */
4841 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4850 for (i
= 0; i
< blob
->cbData
; i
++)
4852 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4861 SetLastError(CRYPT_E_ASN1_BADTAG
);
4867 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4868 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4869 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4877 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4878 lpszStructType
, pbEncoded
, cbEncoded
,
4879 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4882 *pcbStructInfo
= bytesNeeded
;
4883 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4884 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4886 CRYPT_INTEGER_BLOB
*blob
;
4888 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4889 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4890 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4891 blob
->pbData
= (BYTE
*)pvStructInfo
+
4892 sizeof(CRYPT_INTEGER_BLOB
);
4893 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4894 lpszStructType
, pbEncoded
, cbEncoded
,
4895 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4900 __EXCEPT(page_fault
)
4902 SetLastError(STATUS_ACCESS_VIOLATION
);
4909 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4910 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4911 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4917 *pcbStructInfo
= sizeof(int);
4922 if (pbEncoded
[0] == ASN_ENUMERATED
)
4924 unsigned int val
= 0, i
;
4928 SetLastError(CRYPT_E_ASN1_EOD
);
4931 else if (pbEncoded
[1] == 0)
4933 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4938 /* A little strange looking, but we have to accept a sign byte:
4939 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4940 * assuming a small length is okay here, it has to be in short
4943 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4945 SetLastError(CRYPT_E_ASN1_LARGE
);
4948 for (i
= 0; i
< pbEncoded
[1]; i
++)
4951 val
|= pbEncoded
[2 + i
];
4953 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4954 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4956 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4957 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4958 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4964 SetLastError(CRYPT_E_ASN1_BADTAG
);
4968 __EXCEPT(page_fault
)
4970 SetLastError(STATUS_ACCESS_VIOLATION
);
4977 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4980 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4985 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4987 if (!isdigit(*(pbEncoded))) \
4989 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4995 (word) += *(pbEncoded)++ - '0'; \
5000 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
5001 SYSTEMTIME
*sysTime
)
5008 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
5010 WORD hours
, minutes
= 0;
5011 BYTE sign
= *pbEncoded
++;
5014 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
5015 if (ret
&& hours
>= 24)
5017 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5022 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
5023 if (ret
&& minutes
>= 60)
5025 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5033 sysTime
->wHour
+= hours
;
5034 sysTime
->wMinute
+= minutes
;
5038 if (hours
> sysTime
->wHour
)
5041 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
5044 sysTime
->wHour
-= hours
;
5045 if (minutes
> sysTime
->wMinute
)
5048 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
5051 sysTime
->wMinute
-= minutes
;
5056 __EXCEPT(page_fault
)
5058 SetLastError(STATUS_ACCESS_VIOLATION
);
5065 #define MIN_ENCODED_TIME_LENGTH 10
5067 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
5068 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5069 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5075 *pcbStructInfo
= sizeof(FILETIME
);
5081 if (pbEncoded
[0] == ASN_UTCTIME
)
5085 SetLastError(CRYPT_E_ASN1_EOD
);
5088 else if (pbEncoded
[1] > 0x7f)
5090 /* long-form date strings really can't be valid */
5091 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5096 SYSTEMTIME sysTime
= { 0 };
5097 BYTE len
= pbEncoded
[1];
5099 if (len
< MIN_ENCODED_TIME_LENGTH
)
5101 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5107 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
5108 if (sysTime
.wYear
>= 50)
5109 sysTime
.wYear
+= 1900;
5111 sysTime
.wYear
+= 2000;
5112 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5113 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5114 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5115 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
5118 if (len
>= 2 && isdigit(*pbEncoded
) &&
5119 isdigit(*(pbEncoded
+ 1)))
5120 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5122 else if (isdigit(*pbEncoded
))
5123 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
5126 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5129 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5130 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5133 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5134 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5135 ret
= SystemTimeToFileTime(&sysTime
,
5136 (FILETIME
*)pvStructInfo
);
5143 SetLastError(CRYPT_E_ASN1_BADTAG
);
5147 __EXCEPT(page_fault
)
5149 SetLastError(STATUS_ACCESS_VIOLATION
);
5156 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
5157 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5158 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5164 *pcbStructInfo
= sizeof(FILETIME
);
5170 if (pbEncoded
[0] == ASN_GENERALTIME
)
5174 SetLastError(CRYPT_E_ASN1_EOD
);
5177 else if (pbEncoded
[1] > 0x7f)
5179 /* long-form date strings really can't be valid */
5180 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5185 BYTE len
= pbEncoded
[1];
5187 if (len
< MIN_ENCODED_TIME_LENGTH
)
5189 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5194 SYSTEMTIME sysTime
= { 0 };
5197 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
5198 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5199 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5200 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5203 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5206 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5208 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
5215 /* workaround macro weirdness */
5216 digits
= min(len
, 3);
5217 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
5218 sysTime
.wMilliseconds
);
5221 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5224 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5225 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5228 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5229 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5230 ret
= SystemTimeToFileTime(&sysTime
,
5231 (FILETIME
*)pvStructInfo
);
5238 SetLastError(CRYPT_E_ASN1_BADTAG
);
5242 __EXCEPT(page_fault
)
5244 SetLastError(STATUS_ACCESS_VIOLATION
);
5251 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5252 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5253 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5259 if (pbEncoded
[0] == ASN_UTCTIME
)
5260 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5261 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5263 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5264 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5265 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5266 pvStructInfo
, pcbStructInfo
);
5269 SetLastError(CRYPT_E_ASN1_BADTAG
);
5273 __EXCEPT(page_fault
)
5275 SetLastError(STATUS_ACCESS_VIOLATION
);
5282 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5283 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5284 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5290 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5292 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5294 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5299 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5300 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5302 ptr
= pbEncoded
+ 1 + lenBytes
;
5303 remainingLen
= dataLen
;
5304 while (ret
&& remainingLen
)
5308 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5311 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5313 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5314 ptr
+= 1 + nextLenBytes
+ nextLen
;
5315 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5316 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5317 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5323 CRYPT_SEQUENCE_OF_ANY
*seq
;
5327 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5328 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5330 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5331 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5332 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5333 seq
->cValue
= cValue
;
5334 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5336 nextPtr
= (BYTE
*)seq
->rgValue
+
5337 cValue
* sizeof(CRYPT_DER_BLOB
);
5338 ptr
= pbEncoded
+ 1 + lenBytes
;
5339 remainingLen
= dataLen
;
5341 while (ret
&& remainingLen
)
5345 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5348 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5350 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5352 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5353 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5356 seq
->rgValue
[i
].pbData
= nextPtr
;
5357 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5359 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5361 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5362 ptr
+= 1 + nextLenBytes
+ nextLen
;
5372 SetLastError(CRYPT_E_ASN1_BADTAG
);
5376 __EXCEPT(page_fault
)
5378 SetLastError(STATUS_ACCESS_VIOLATION
);
5385 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5386 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5387 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5391 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5393 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5394 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5395 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5397 if (!pvStructInfo
&& !pcbStructInfo
)
5399 SetLastError(ERROR_INVALID_PARAMETER
);
5402 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5403 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5405 SetLastError(ERROR_FILE_NOT_FOUND
);
5410 SetLastError(CRYPT_E_ASN1_EOD
);
5413 if (cbEncoded
> MAX_ENCODED_LEN
)
5415 SetLastError(CRYPT_E_ASN1_LARGE
);
5419 SetLastError(NOERROR
);
5420 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5421 *(BYTE
**)pvStructInfo
= NULL
;
5422 if (!HIWORD(lpszStructType
))
5424 switch (LOWORD(lpszStructType
))
5426 case (WORD
)X509_CERT
:
5427 decodeFunc
= CRYPT_AsnDecodeCert
;
5429 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5430 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5432 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5433 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5435 case (WORD
)X509_EXTENSIONS
:
5436 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5438 case (WORD
)X509_NAME
:
5439 decodeFunc
= CRYPT_AsnDecodeName
;
5441 case (WORD
)X509_PUBLIC_KEY_INFO
:
5442 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5444 case (WORD
)X509_ALTERNATE_NAME
:
5445 decodeFunc
= CRYPT_AsnDecodeAltName
;
5447 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5448 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5450 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5451 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5453 case (WORD
)X509_OCTET_STRING
:
5454 decodeFunc
= CRYPT_AsnDecodeOctets
;
5456 case (WORD
)X509_BITS
:
5457 case (WORD
)X509_KEY_USAGE
:
5458 decodeFunc
= CRYPT_AsnDecodeBits
;
5460 case (WORD
)X509_INTEGER
:
5461 decodeFunc
= CRYPT_AsnDecodeInt
;
5463 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5464 decodeFunc
= CRYPT_AsnDecodeInteger
;
5466 case (WORD
)X509_MULTI_BYTE_UINT
:
5467 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5469 case (WORD
)X509_ENUMERATED
:
5470 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5472 case (WORD
)X509_CHOICE_OF_TIME
:
5473 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5475 case (WORD
)X509_SEQUENCE_OF_ANY
:
5476 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5478 case (WORD
)PKCS_UTC_TIME
:
5479 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5482 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5485 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5486 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5487 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5488 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5489 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5490 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5491 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5492 decodeFunc
= CRYPT_AsnDecodeBits
;
5493 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5494 decodeFunc
= CRYPT_AsnDecodeOctets
;
5495 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5496 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5497 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5498 decodeFunc
= CRYPT_AsnDecodeAltName
;
5499 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5500 decodeFunc
= CRYPT_AsnDecodeAltName
;
5501 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5502 decodeFunc
= CRYPT_AsnDecodeAltName
;
5503 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5504 decodeFunc
= CRYPT_AsnDecodeAltName
;
5505 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5506 decodeFunc
= CRYPT_AsnDecodeAltName
;
5508 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5509 debugstr_a(lpszStructType
));
5511 decodeFunc
= (CryptDecodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
5512 lpszStructType
, "CryptDecodeObjectEx", &lib
);
5514 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5515 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5517 SetLastError(ERROR_FILE_NOT_FOUND
);
5523 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5524 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5526 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5527 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5530 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5531 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5532 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5537 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5538 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5541 if (!pszPublicKeyObjId
)
5542 pszPublicKeyObjId
= szOID_RSA_RSA
;
5543 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5547 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5550 LPBYTE pubKey
= HeapAlloc(GetProcessHeap(), 0, keySize
);
5554 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
5558 DWORD encodedLen
= 0;
5560 ret
= CryptEncodeObject(dwCertEncodingType
,
5561 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5564 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5565 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5568 *pcbInfo
= sizeNeeded
;
5569 else if (*pcbInfo
< sizeNeeded
)
5571 SetLastError(ERROR_MORE_DATA
);
5572 *pcbInfo
= sizeNeeded
;
5577 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5578 sizeof(CERT_PUBLIC_KEY_INFO
);
5579 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5581 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5582 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5583 pInfo
->PublicKey
.pbData
=
5584 (BYTE
*)pInfo
->Algorithm
.pszObjId
5585 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5586 pInfo
->PublicKey
.cbData
= encodedLen
;
5587 pInfo
->PublicKey
.cUnusedBits
= 0;
5588 ret
= CryptEncodeObject(dwCertEncodingType
,
5589 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5590 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5594 HeapFree(GetProcessHeap(), 0, pubKey
);
5599 CryptDestroyKey(key
);
5604 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5605 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5606 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5608 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5609 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5610 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5613 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5616 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5617 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5622 SetLastError(ERROR_INVALID_PARAMETER
);
5626 if (pszPublicKeyObjId
)
5627 exportFunc
= CRYPT_GetFunc(dwCertEncodingType
, pszPublicKeyObjId
,
5628 CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
, &lib
);
5630 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
5631 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5632 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5638 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5639 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5641 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5645 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5646 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5647 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5650 DWORD pubKeySize
= 0;
5652 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5653 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5655 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5656 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5659 LPBYTE pubKey
= HeapAlloc(GetProcessHeap(), 0, pubKeySize
);
5663 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5664 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5667 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5669 HeapFree(GetProcessHeap(), 0, pubKey
);
5677 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5678 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5679 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5681 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5682 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5683 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5686 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5689 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5690 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5692 importFunc
= CRYPT_GetFunc(dwCertEncodingType
, pInfo
->Algorithm
.pszObjId
,
5693 CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, &lib
);
5695 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
5696 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,