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
37 static _SEH_FILTER(page_fault
)
39 if (_SEH_GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
40 return _SEH_EXECUTE_HANDLER
;
41 return _SEH_CONTINUE_SEARCH
;
44 /* This is a bit arbitrary, but to set some limit: */
45 #define MAX_ENCODED_LEN 0x02000000
47 /* a few asn.1 tags we need */
48 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
49 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
50 //#define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
51 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
52 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
53 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
54 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
55 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
56 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
57 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
59 #define ASN_FLAGS_MASK 0xf0
60 #define ASN_TYPE_MASK 0x0f
62 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
64 static const WCHAR szDllName
[] = { 'D','l','l',0 };
66 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
68 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
69 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
70 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
71 DWORD
, DWORD
, void *, DWORD
*);
72 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
73 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
75 /* Prototypes for built-in encoders/decoders. They follow the Ex style
76 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
77 * built-in functions, but the parameters are retained to simplify
78 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
79 * external DLLs that follow these signatures.
80 * FIXME: some built-in functions are suitable to be called directly by
81 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
82 * and memory allocation if requested), others are only suitable to be called
83 * internally. Comment which are which.
85 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
86 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
87 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
88 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
89 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
90 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
91 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
92 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
93 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
94 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
95 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
96 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
99 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
100 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
101 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
102 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
104 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
105 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
106 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
107 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
108 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
109 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
110 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
111 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
112 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
113 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
114 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
115 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
116 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
117 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
119 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
120 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
121 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
122 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
123 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
124 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
125 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
126 * time, doesn't do memory allocation, and doesn't do exception handling.
127 * (This isn't intended to be the externally-called one.)
129 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
130 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
131 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
132 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
133 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
);
134 /* Assumes algo->Parameters.pbData is set ahead of time */
135 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
136 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
137 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
138 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
139 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
140 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
141 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
142 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
143 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
144 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
145 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
146 * member has been initialized, doesn't do exception handling, and doesn't do
149 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
150 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
151 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
152 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
153 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
154 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
155 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
156 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
157 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
158 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
159 * member has been initialized, doesn't do exception handling, and doesn't do
162 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
163 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
164 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
165 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
166 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
167 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
168 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
169 void *pvStructInfo
, DWORD
*pcbStructInfo
);
171 static char *CRYPT_GetKeyName(DWORD dwEncodingType
, LPCSTR pszFuncName
,
174 static const char szEncodingTypeFmt
[] =
175 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
177 char numericOID
[7]; /* enough for "#65535" */
181 /* MSDN says the encoding type is a mask, but it isn't treated that way.
182 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
183 * "EncodingType 2" would be expected if it were a mask. Instead native
184 * stores values in "EncodingType 3".
188 snprintf(numericOID
, sizeof(numericOID
), "#%d", LOWORD(pszOID
));
194 /* This is enough: the lengths of the two string parameters are explicitly
195 * counted, and we need up to five additional characters for the encoding
196 * type. These are covered by the "%d", "%s", and "%s" characters in the
197 * format specifier that are removed by sprintf.
199 len
= sizeof(szEncodingTypeFmt
) + lstrlenA(pszFuncName
) + lstrlenA(oid
);
200 szKey
= CryptMemAlloc(len
);
202 sprintf(szKey
, szEncodingTypeFmt
, dwEncodingType
, pszFuncName
, oid
);
206 BOOL WINAPI
CryptRegisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
207 LPCSTR pszOID
, LPCWSTR pwszDll
, LPCSTR pszOverrideFuncName
)
213 TRACE("%lx %s %s %s %s\n", dwEncodingType
, pszFuncName
, pszOID
,
214 debugstr_w(pwszDll
), pszOverrideFuncName
);
216 /* This only registers functions for encoding certs, not messages */
217 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
220 /* Native does nothing pwszDll is NULL */
224 /* I'm not matching MS bug for bug here, because I doubt any app depends on
226 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
227 * it creates would never be used
228 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
229 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
231 if (!pszFuncName
|| !pszOID
)
233 SetLastError(ERROR_INVALID_PARAMETER
);
237 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
238 TRACE("Key name is %s\n", debugstr_a(szKey
));
243 r
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
245 if(r
!= ERROR_SUCCESS
)
248 /* write the values */
249 if (pszOverrideFuncName
)
250 RegSetValueExA(hKey
, "FuncName", 0, REG_SZ
, (const BYTE
*)pszOverrideFuncName
,
251 lstrlenA(pszOverrideFuncName
) + 1);
252 RegSetValueExW(hKey
, szDllName
, 0, REG_SZ
, (const BYTE
*) pwszDll
,
253 (lstrlenW(pwszDll
) + 1) * sizeof (WCHAR
));
259 BOOL WINAPI
CryptUnregisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
265 TRACE("%lx %s %s\n", dwEncodingType
, pszFuncName
, pszOID
);
267 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
270 if (!pszFuncName
|| !pszOID
)
272 SetLastError(ERROR_INVALID_PARAMETER
);
276 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
277 rc
= RegDeleteKeyA(HKEY_LOCAL_MACHINE
, szKey
);
281 return rc
? FALSE
: TRUE
;
284 BOOL WINAPI
CryptGetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
285 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD
*pdwValueType
, BYTE
*pbValueData
,
292 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType
, debugstr_a(pszFuncName
),
293 debugstr_a(pszOID
), debugstr_w(pwszValueName
), pdwValueType
, pbValueData
,
296 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
299 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
301 SetLastError(ERROR_INVALID_PARAMETER
);
305 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
306 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
312 rc
= RegQueryValueExW(hKey
, pwszValueName
, NULL
, pdwValueType
,
313 pbValueData
, pcbValueData
);
318 return rc
? FALSE
: TRUE
;
321 BOOL WINAPI
CryptSetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
322 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD dwValueType
,
323 const BYTE
*pbValueData
, DWORD cbValueData
)
329 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType
, debugstr_a(pszFuncName
),
330 debugstr_a(pszOID
), debugstr_w(pwszValueName
), dwValueType
, pbValueData
,
333 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
336 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
338 SetLastError(ERROR_INVALID_PARAMETER
);
342 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
343 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
349 rc
= RegSetValueExW(hKey
, pwszValueName
, 0, dwValueType
, pbValueData
,
355 return rc
? FALSE
: TRUE
;
358 /* Gets the registered function named szFuncName for dwCertEncodingType and
359 * lpszStructType, or NULL if one could not be found. *lib will be set to the
360 * handle of the module it's in, or NULL if no module was loaded. If the
361 * return value is NULL, *lib will also be NULL, to simplify error handling.
363 static void *CRYPT_GetFunc(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
364 LPCSTR szFuncName
, HMODULE
*lib
)
367 char *szKey
= CRYPT_GetKeyName(dwCertEncodingType
, szFuncName
,
369 const char *funcName
;
372 DWORD type
, size
= 0;
374 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType
, debugstr_a(lpszStructType
),
375 debugstr_a(szFuncName
), lib
);
378 r
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
380 if(r
!= ERROR_SUCCESS
)
383 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, NULL
, &size
);
384 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
386 funcName
= CryptMemAlloc(size
);
387 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, (LPBYTE
)funcName
,
391 funcName
= szFuncName
;
392 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, NULL
, &size
);
393 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
395 LPWSTR dllName
= CryptMemAlloc(size
);
397 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, (LPBYTE
)dllName
,
399 *lib
= LoadLibraryW(dllName
);
402 ret
= GetProcAddress(*lib
, funcName
);
405 /* Unload the library, the caller doesn't want to unload it
406 * when the return value is NULL.
412 CryptMemFree(dllName
);
414 if (funcName
!= szFuncName
)
415 CryptMemFree((char *)funcName
);
416 TRACE("returning %p\n", ret
);
420 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
421 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
425 CryptEncodeObjectFunc pCryptEncodeObject
;
427 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
428 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
431 if (!pbEncoded
&& !pcbEncoded
)
433 SetLastError(ERROR_INVALID_PARAMETER
);
437 /* Try registered DLL first.. */
439 (CryptEncodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
440 lpszStructType
, CRYPT_OID_ENCODE_OBJECT_FUNC
, &lib
);
441 if (pCryptEncodeObject
)
443 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
444 pvStructInfo
, pbEncoded
, pcbEncoded
);
449 /* If not, use CryptEncodeObjectEx */
450 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
451 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
456 /* Helper function to check *pcbEncoded, set it to the required size, and
457 * optionally to allocate memory. Assumes pbEncoded is not NULL.
458 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
459 * pointer to the newly allocated memory.
461 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
462 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
467 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
469 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
470 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
472 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
473 if (!*(BYTE
**)pbEncoded
)
476 *pcbEncoded
= bytesNeeded
;
478 else if (bytesNeeded
> *pcbEncoded
)
480 *pcbEncoded
= bytesNeeded
;
481 SetLastError(ERROR_MORE_DATA
);
487 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
489 DWORD bytesNeeded
, significantBytes
= 0;
497 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
498 temp
<<= 8, significantBytes
--)
500 bytesNeeded
= significantBytes
+ 1;
504 *pcbEncoded
= bytesNeeded
;
507 if (*pcbEncoded
< bytesNeeded
)
509 SetLastError(ERROR_MORE_DATA
);
513 *pbEncoded
= (BYTE
)len
;
518 *pbEncoded
++ = significantBytes
| 0x80;
519 for (i
= 0; i
< significantBytes
; i
++)
521 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
525 *pcbEncoded
= bytesNeeded
;
529 struct AsnEncodeSequenceItem
531 const void *pvStructInfo
;
532 CryptEncodeObjectExFunc encodeFunc
;
533 DWORD size
; /* used during encoding, not for your use */
536 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
537 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
538 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
541 DWORD i
, dataLen
= 0;
543 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
544 pbEncoded
, *pcbEncoded
);
545 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
547 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
548 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
549 NULL
, &items
[i
].size
);
550 dataLen
+= items
[i
].size
;
554 DWORD lenBytes
, bytesNeeded
;
556 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
557 bytesNeeded
= 1 + lenBytes
+ dataLen
;
559 *pcbEncoded
= bytesNeeded
;
562 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
563 pcbEncoded
, bytesNeeded
)))
565 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
566 pbEncoded
= *(BYTE
**)pbEncoded
;
567 *pbEncoded
++ = ASN_SEQUENCE
;
568 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
569 pbEncoded
+= lenBytes
;
570 for (i
= 0; ret
&& i
< cItem
; i
++)
572 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
573 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
574 NULL
, pbEncoded
, &items
[i
].size
);
575 pbEncoded
+= items
[i
].size
;
580 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
584 struct AsnConstructedItem
587 const void *pvStructInfo
;
588 CryptEncodeObjectExFunc encodeFunc
;
591 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
592 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
593 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
596 const struct AsnConstructedItem
*item
=
597 (const struct AsnConstructedItem
*)pvStructInfo
;
600 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
601 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
603 DWORD dataLen
, bytesNeeded
;
605 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
606 bytesNeeded
= 1 + dataLen
+ len
;
608 *pcbEncoded
= bytesNeeded
;
609 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
610 pbEncoded
, pcbEncoded
, bytesNeeded
)))
612 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
613 pbEncoded
= *(BYTE
**)pbEncoded
;
614 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
615 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
616 pbEncoded
+= dataLen
;
617 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
618 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
625 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
626 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
627 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
629 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
632 /* CERT_V1 is not encoded */
640 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
642 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
643 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
648 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
649 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
650 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
652 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
657 *pcbEncoded
= blob
->cbData
;
660 else if (*pcbEncoded
< blob
->cbData
)
662 *pcbEncoded
= blob
->cbData
;
663 SetLastError(ERROR_MORE_DATA
);
669 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
670 *pcbEncoded
= blob
->cbData
;
676 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
677 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
678 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
681 /* This has two filetimes in a row, a NotBefore and a NotAfter */
682 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
683 struct AsnEncodeSequenceItem items
[] = {
684 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
685 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
688 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
689 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
694 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
695 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
696 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
699 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
700 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
702 struct AsnEncodeSequenceItem items
[] = {
703 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
704 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
707 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
708 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
713 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
714 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
715 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
721 const CERT_PUBLIC_KEY_INFO
*info
=
722 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
723 struct AsnEncodeSequenceItem items
[] = {
724 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
725 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
728 TRACE("Encoding public key with OID %s\n",
729 debugstr_a(info
->Algorithm
.pszObjId
));
730 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
731 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
734 _SEH_EXCEPT(page_fault
)
736 SetLastError(STATUS_ACCESS_VIOLATION
);
743 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
744 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
745 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
751 const CERT_SIGNED_CONTENT_INFO
*info
=
752 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
753 struct AsnEncodeSequenceItem items
[] = {
754 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
755 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
756 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
759 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
760 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
761 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
762 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
765 _SEH_EXCEPT(page_fault
)
767 SetLastError(STATUS_ACCESS_VIOLATION
);
774 /* Like in Windows, this blithely ignores the validity of the passed-in
775 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
776 * decode properly, see CRYPT_AsnDecodeCertInfo.
778 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
779 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
780 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
786 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
787 struct AsnEncodeSequenceItem items
[10] = {
788 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
789 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
790 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
791 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
792 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
793 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
794 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
797 struct AsnConstructedItem constructed
[3] = { { 0 } };
798 DWORD cItem
= 7, cConstructed
= 0;
800 if (info
->IssuerUniqueId
.cbData
)
802 constructed
[cConstructed
].tag
= 1;
803 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
804 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
805 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
806 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
810 if (info
->SubjectUniqueId
.cbData
)
812 constructed
[cConstructed
].tag
= 2;
813 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
814 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
815 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
816 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
820 if (info
->cExtension
)
822 constructed
[cConstructed
].tag
= 3;
823 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
824 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
825 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
826 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
831 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
832 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
834 _SEH_EXCEPT(page_fault
)
836 SetLastError(STATUS_ACCESS_VIOLATION
);
843 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
844 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
846 struct AsnEncodeSequenceItem items
[3] = {
847 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
848 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
854 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
856 if (entry
->cExtension
)
858 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
859 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
863 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
864 pbEncoded
, pcbEncoded
);
866 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
870 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
871 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
872 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
874 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
875 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
876 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
877 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
880 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
884 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
888 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
889 bytesNeeded
= 1 + lenBytes
+ dataLen
;
891 *pcbEncoded
= bytesNeeded
;
894 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
895 pcbEncoded
, bytesNeeded
)))
897 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
898 pbEncoded
= *(BYTE
**)pbEncoded
;
899 *pbEncoded
++ = ASN_SEQUENCEOF
;
900 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
901 pbEncoded
+= lenBytes
;
902 for (i
= 0; i
< cCRLEntry
; i
++)
904 DWORD size
= dataLen
;
906 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
915 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
916 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
917 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
919 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
922 /* CRL_V1 is not encoded */
929 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
930 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
934 /* Like in Windows, this blithely ignores the validity of the passed-in
935 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
936 * decode properly, see CRYPT_AsnDecodeCRLInfo.
938 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
939 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
940 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
946 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
947 struct AsnEncodeSequenceItem items
[7] = {
948 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
949 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
950 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
951 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
956 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
958 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
959 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
964 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
965 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
968 if (info
->cExtension
)
970 items
[cItem
].pvStructInfo
= &info
->cExtension
;
971 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
975 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
976 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
978 _SEH_EXCEPT(page_fault
)
980 SetLastError(STATUS_ACCESS_VIOLATION
);
987 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
991 struct AsnEncodeSequenceItem items
[3] = {
992 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
998 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
1002 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
1003 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1006 items
[cItem
].pvStructInfo
= &ext
->Value
;
1007 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1010 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
1011 pbEncoded
, pcbEncoded
);
1012 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1016 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
1017 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1018 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1024 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1025 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
1028 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
1032 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
1036 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1037 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1039 *pcbEncoded
= bytesNeeded
;
1042 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1043 pcbEncoded
, bytesNeeded
)))
1045 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1046 pbEncoded
= *(BYTE
**)pbEncoded
;
1047 *pbEncoded
++ = ASN_SEQUENCEOF
;
1048 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1049 pbEncoded
+= lenBytes
;
1050 for (i
= 0; i
< exts
->cExtension
; i
++)
1052 DWORD size
= dataLen
;
1054 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
1062 _SEH_EXCEPT(page_fault
)
1064 SetLastError(STATUS_ACCESS_VIOLATION
);
1071 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
1072 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1073 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1075 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
1076 DWORD bytesNeeded
= 0, lenBytes
;
1081 TRACE("%s\n", debugstr_a(pszObjId
));
1088 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
1090 SetLastError(CRYPT_E_ASN1_ERROR
);
1094 firstByte
= val1
* 40 + val2
;
1095 ptr
= pszObjId
+ firstPos
;
1100 /* note I assume each component is at most 32-bits long in base 2 */
1101 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
1103 if (val1
>= 0x10000000)
1105 else if (val1
>= 0x200000)
1107 else if (val1
>= 0x4000)
1109 else if (val1
>= 0x80)
1119 SetLastError(CRYPT_E_ASN1_ERROR
);
1123 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1127 bytesNeeded
+= 1 + lenBytes
;
1130 if (*pcbEncoded
< bytesNeeded
)
1132 SetLastError(ERROR_MORE_DATA
);
1137 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
1138 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
1139 pbEncoded
+= lenBytes
;
1145 *pbEncoded
++ = firstByte
;
1146 ptr
= pszObjId
+ firstPos
;
1149 sscanf(ptr
, "%d%n", &val
, &pos
);
1151 unsigned char outBytes
[5];
1154 if (val
>= 0x10000000)
1156 else if (val
>= 0x200000)
1158 else if (val
>= 0x4000)
1160 else if (val
>= 0x80)
1164 for (i
= numBytes
; i
> 0; i
--)
1166 outBytes
[i
- 1] = val
& 0x7f;
1169 for (i
= 0; i
< numBytes
- 1; i
++)
1170 *pbEncoded
++ = outBytes
[i
] | 0x80;
1171 *pbEncoded
++ = outBytes
[i
];
1180 *pcbEncoded
= bytesNeeded
;
1184 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1185 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1188 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1191 switch (value
->dwValueType
)
1193 case CERT_RDN_NUMERIC_STRING
:
1194 tag
= ASN_NUMERICSTRING
;
1195 encodedLen
= value
->Value
.cbData
;
1197 case CERT_RDN_PRINTABLE_STRING
:
1198 tag
= ASN_PRINTABLESTRING
;
1199 encodedLen
= value
->Value
.cbData
;
1201 case CERT_RDN_IA5_STRING
:
1202 tag
= ASN_IA5STRING
;
1203 encodedLen
= value
->Value
.cbData
;
1205 case CERT_RDN_ANY_TYPE
:
1206 /* explicitly disallowed */
1207 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1210 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
1213 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1214 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1217 if (*pcbEncoded
< bytesNeeded
)
1219 SetLastError(ERROR_MORE_DATA
);
1225 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1226 pbEncoded
+= lenBytes
;
1227 switch (value
->dwValueType
)
1229 case CERT_RDN_NUMERIC_STRING
:
1230 case CERT_RDN_PRINTABLE_STRING
:
1231 case CERT_RDN_IA5_STRING
:
1232 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1236 *pcbEncoded
= bytesNeeded
;
1240 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1241 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1243 DWORD bytesNeeded
= 0, lenBytes
, size
;
1246 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1247 0, NULL
, NULL
, &size
);
1250 bytesNeeded
+= size
;
1251 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1252 * with dwValueType, so "cast" it to get its encoded size
1254 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1255 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1258 bytesNeeded
+= size
;
1259 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1260 bytesNeeded
+= 1 + lenBytes
;
1263 if (*pcbEncoded
< bytesNeeded
)
1265 SetLastError(ERROR_MORE_DATA
);
1270 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SEQUENCE
;
1271 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1273 pbEncoded
+= lenBytes
;
1274 size
= bytesNeeded
- 1 - lenBytes
;
1275 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1276 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1280 size
= bytesNeeded
- 1 - lenBytes
- size
;
1281 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1282 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1287 *pcbEncoded
= bytesNeeded
;
1293 static int BLOBComp(const void *l
, const void *r
)
1295 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1298 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1299 ret
= a
->cbData
- b
->cbData
;
1303 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1305 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1306 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1309 CRYPT_DER_BLOB
*blobs
= NULL
;
1313 DWORD bytesNeeded
= 0, lenBytes
, i
;
1319 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1323 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1325 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1327 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1328 NULL
, &blobs
[i
].cbData
);
1330 bytesNeeded
+= blobs
[i
].cbData
;
1334 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1335 bytesNeeded
+= 1 + lenBytes
;
1338 if (*pcbEncoded
< bytesNeeded
)
1340 SetLastError(ERROR_MORE_DATA
);
1345 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1347 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1348 if (!blobs
[i
].pbData
)
1351 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1352 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1357 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1359 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1360 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1362 pbEncoded
+= lenBytes
;
1363 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1365 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1366 pbEncoded
+= blobs
[i
].cbData
;
1371 *pcbEncoded
= bytesNeeded
;
1375 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1376 CryptMemFree(blobs
[i
].pbData
);
1379 _SEH_EXCEPT(page_fault
)
1381 SetLastError(STATUS_ACCESS_VIOLATION
);
1385 CryptMemFree(blobs
);
1389 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1390 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1391 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1397 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1398 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1400 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1402 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1404 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1407 bytesNeeded
+= size
;
1409 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1410 bytesNeeded
+= 1 + lenBytes
;
1414 *pcbEncoded
= bytesNeeded
;
1417 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1418 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1420 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1421 pbEncoded
= *(BYTE
**)pbEncoded
;
1422 *pbEncoded
++ = ASN_SEQUENCEOF
;
1423 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1425 pbEncoded
+= lenBytes
;
1426 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1429 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1430 &info
->rgRDN
[i
], pbEncoded
, &size
);
1434 bytesNeeded
-= size
;
1441 _SEH_EXCEPT(page_fault
)
1443 SetLastError(STATUS_ACCESS_VIOLATION
);
1450 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1451 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1452 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1454 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1463 else if (*pcbEncoded
< 3)
1466 SetLastError(ERROR_MORE_DATA
);
1472 *pbEncoded
++ = ASN_BOOL
;
1474 *pbEncoded
++ = val
? 0xff : 0;
1477 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1481 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1482 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1488 switch (entry
->dwAltNameChoice
)
1490 case CERT_ALT_NAME_RFC822_NAME
:
1491 case CERT_ALT_NAME_DNS_NAME
:
1492 case CERT_ALT_NAME_URL
:
1497 /* Not + 1: don't encode the NULL-terminator */
1498 dataLen
= lstrlenW(entry
->pwszURL
);
1499 for (i
= 0; ret
&& i
< dataLen
; i
++)
1501 if (entry
->pwszURL
[i
] > 0x7f)
1503 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1512 case CERT_ALT_NAME_IP_ADDRESS
:
1513 dataLen
= entry
->IPAddress
.cbData
;
1515 case CERT_ALT_NAME_REGISTERED_ID
:
1516 /* FIXME: encode OID */
1517 case CERT_ALT_NAME_OTHER_NAME
:
1518 case CERT_ALT_NAME_DIRECTORY_NAME
:
1519 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1522 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1527 DWORD bytesNeeded
, lenBytes
;
1529 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1530 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1532 *pcbEncoded
= bytesNeeded
;
1533 else if (*pcbEncoded
< bytesNeeded
)
1535 SetLastError(ERROR_MORE_DATA
);
1536 *pcbEncoded
= bytesNeeded
;
1541 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1542 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1543 pbEncoded
+= lenBytes
;
1544 switch (entry
->dwAltNameChoice
)
1546 case CERT_ALT_NAME_RFC822_NAME
:
1547 case CERT_ALT_NAME_DNS_NAME
:
1548 case CERT_ALT_NAME_URL
:
1552 for (i
= 0; i
< dataLen
; i
++)
1553 *pbEncoded
++ = (BYTE
)entry
->pwszURL
[i
];
1556 case CERT_ALT_NAME_IP_ADDRESS
:
1557 memcpy(pbEncoded
, entry
->IPAddress
.pbData
, dataLen
);
1561 *pcbEncoded
= bytesNeeded
;
1564 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1568 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1569 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1570 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1576 const CERT_ALT_NAME_INFO
*info
=
1577 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1579 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1582 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1583 * can't encode an erroneous entry index if it's bigger than this.
1585 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1589 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1593 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1595 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1596 * the bad character, now set the index of the bad
1599 *pcbEncoded
= (BYTE
)i
<<
1600 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1605 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1606 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1609 *pcbEncoded
= bytesNeeded
;
1614 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1615 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1617 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1618 pbEncoded
= *(BYTE
**)pbEncoded
;
1619 *pbEncoded
++ = ASN_SEQUENCEOF
;
1620 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1621 pbEncoded
+= lenBytes
;
1622 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1624 DWORD len
= dataLen
;
1626 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1638 _SEH_EXCEPT(page_fault
)
1640 SetLastError(STATUS_ACCESS_VIOLATION
);
1647 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1648 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1649 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1655 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1656 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1657 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1662 items
[cItem
].pvStructInfo
= &info
->fCA
;
1663 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1666 if (info
->fPathLenConstraint
)
1668 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1669 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1672 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1673 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1675 _SEH_EXCEPT(page_fault
)
1677 SetLastError(STATUS_ACCESS_VIOLATION
);
1684 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1685 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1686 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1692 const BLOBHEADER
*hdr
=
1693 (const BLOBHEADER
*)pvStructInfo
;
1695 if (hdr
->bType
!= PUBLICKEYBLOB
)
1697 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1702 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1703 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1704 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1705 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1706 struct AsnEncodeSequenceItem items
[] = {
1707 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1708 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1711 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1712 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1716 _SEH_EXCEPT(page_fault
)
1718 SetLastError(STATUS_ACCESS_VIOLATION
);
1725 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1726 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1727 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1733 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1734 DWORD bytesNeeded
, lenBytes
;
1736 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1737 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1739 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1740 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1743 *pcbEncoded
= bytesNeeded
;
1748 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1749 pcbEncoded
, bytesNeeded
)))
1751 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1752 pbEncoded
= *(BYTE
**)pbEncoded
;
1753 *pbEncoded
++ = ASN_OCTETSTRING
;
1754 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1755 pbEncoded
+= lenBytes
;
1757 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1761 _SEH_EXCEPT(page_fault
)
1763 SetLastError(STATUS_ACCESS_VIOLATION
);
1767 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1771 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1772 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1773 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1779 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1780 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1783 /* yep, MS allows cUnusedBits to be >= 8 */
1784 if (!blob
->cUnusedBits
)
1786 dataBytes
= blob
->cbData
;
1789 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1791 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1792 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1800 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1801 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1804 *pcbEncoded
= bytesNeeded
;
1809 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1810 pcbEncoded
, bytesNeeded
)))
1812 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1813 pbEncoded
= *(BYTE
**)pbEncoded
;
1814 *pbEncoded
++ = ASN_BITSTRING
;
1815 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1816 pbEncoded
+= lenBytes
;
1817 *pbEncoded
++ = unusedBits
;
1820 BYTE mask
= 0xff << unusedBits
;
1824 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1825 pbEncoded
+= dataBytes
- 1;
1827 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1832 _SEH_EXCEPT(page_fault
)
1834 SetLastError(STATUS_ACCESS_VIOLATION
);
1841 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1842 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1843 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1849 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1850 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1855 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
1860 for (i
= 0; i
< newBlob
.cbData
; i
++)
1861 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1867 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1868 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1869 CryptMemFree(newBlob
.pbData
);
1871 _SEH_EXCEPT(page_fault
)
1873 SetLastError(STATUS_ACCESS_VIOLATION
);
1880 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1881 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1882 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1884 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1886 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1887 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1890 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1891 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1892 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1898 DWORD significantBytes
, lenBytes
;
1899 BYTE padByte
= 0, bytesNeeded
;
1901 const CRYPT_INTEGER_BLOB
*blob
=
1902 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1904 significantBytes
= blob
->cbData
;
1905 if (significantBytes
)
1907 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1909 /* negative, lop off leading (little-endian) 0xffs */
1910 for (; significantBytes
> 0 &&
1911 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1913 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1921 /* positive, lop off leading (little-endian) zeroes */
1922 for (; significantBytes
> 0 &&
1923 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1925 if (significantBytes
== 0)
1926 significantBytes
= 1;
1927 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1935 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1937 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1938 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1943 *pcbEncoded
= bytesNeeded
;
1948 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1949 pcbEncoded
, bytesNeeded
)))
1951 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1952 pbEncoded
= *(BYTE
**)pbEncoded
;
1953 *pbEncoded
++ = ASN_INTEGER
;
1956 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1957 pbEncoded
+= lenBytes
;
1958 *pbEncoded
++ = padByte
;
1962 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1963 pbEncoded
+= lenBytes
;
1965 for (; significantBytes
> 0; significantBytes
--)
1966 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1970 _SEH_EXCEPT(page_fault
)
1972 SetLastError(STATUS_ACCESS_VIOLATION
);
1979 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1980 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1981 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1987 DWORD significantBytes
, lenBytes
;
1990 const CRYPT_INTEGER_BLOB
*blob
=
1991 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1993 significantBytes
= blob
->cbData
;
1994 if (significantBytes
)
1996 /* positive, lop off leading (little-endian) zeroes */
1997 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2000 if (significantBytes
== 0)
2001 significantBytes
= 1;
2002 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2006 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2008 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2009 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2014 *pcbEncoded
= bytesNeeded
;
2019 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2020 pcbEncoded
, bytesNeeded
)))
2022 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2023 pbEncoded
= *(BYTE
**)pbEncoded
;
2024 *pbEncoded
++ = ASN_INTEGER
;
2027 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2028 pbEncoded
+= lenBytes
;
2033 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2034 pbEncoded
+= lenBytes
;
2036 for (; significantBytes
> 0; significantBytes
--)
2037 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2041 _SEH_EXCEPT(page_fault
)
2043 SetLastError(STATUS_ACCESS_VIOLATION
);
2050 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2051 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2052 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2054 CRYPT_INTEGER_BLOB blob
;
2057 /* Encode as an unsigned integer, then change the tag to enumerated */
2058 blob
.cbData
= sizeof(DWORD
);
2059 blob
.pbData
= (BYTE
*)pvStructInfo
;
2060 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2061 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2062 if (ret
&& pbEncoded
)
2064 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2065 pbEncoded
= *(BYTE
**)pbEncoded
;
2066 pbEncoded
[0] = ASN_ENUMERATED
;
2071 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2072 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2073 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2080 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2081 * temporary buffer because the output buffer is not NULL-terminated.
2084 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2088 *pcbEncoded
= bytesNeeded
;
2093 /* Sanity check the year, this is a two-digit year format */
2094 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2096 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2098 SetLastError(CRYPT_E_BAD_ENCODE
);
2103 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2104 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2106 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2107 pbEncoded
= *(BYTE
**)pbEncoded
;
2108 buf
[0] = ASN_UTCTIME
;
2109 buf
[1] = bytesNeeded
- 2;
2110 snprintf(buf
+ 2, sizeof(buf
) - 2,
2111 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2112 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2113 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2114 sysTime
.wMinute
, sysTime
.wSecond
);
2115 memcpy(pbEncoded
, buf
, bytesNeeded
);
2120 _SEH_EXCEPT(page_fault
)
2122 SetLastError(STATUS_ACCESS_VIOLATION
);
2129 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2130 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2131 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2138 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2139 * temporary buffer because the output buffer is not NULL-terminated.
2142 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2146 *pcbEncoded
= bytesNeeded
;
2151 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2154 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2155 pcbEncoded
, bytesNeeded
);
2158 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2159 pbEncoded
= *(BYTE
**)pbEncoded
;
2160 buf
[0] = ASN_GENERALTIME
;
2161 buf
[1] = bytesNeeded
- 2;
2162 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2163 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2164 sysTime
.wMinute
, sysTime
.wSecond
);
2165 memcpy(pbEncoded
, buf
, bytesNeeded
);
2169 _SEH_EXCEPT(page_fault
)
2171 SetLastError(STATUS_ACCESS_VIOLATION
);
2178 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2179 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2180 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2188 /* Check the year, if it's in the UTCTime range call that encode func */
2189 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2191 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2192 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2193 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2195 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2196 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2199 _SEH_EXCEPT(page_fault
)
2201 SetLastError(STATUS_ACCESS_VIOLATION
);
2208 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2209 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2210 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2216 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2217 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2218 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2220 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2221 dataLen
+= seq
->rgValue
[i
].cbData
;
2222 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2223 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2226 *pcbEncoded
= bytesNeeded
;
2231 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2232 pcbEncoded
, bytesNeeded
)))
2234 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2235 pbEncoded
= *(BYTE
**)pbEncoded
;
2236 *pbEncoded
++ = ASN_SEQUENCEOF
;
2237 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2238 pbEncoded
+= lenBytes
;
2239 for (i
= 0; i
< seq
->cValue
; i
++)
2241 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2242 seq
->rgValue
[i
].cbData
);
2243 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2248 _SEH_EXCEPT(page_fault
)
2250 SetLastError(STATUS_ACCESS_VIOLATION
);
2257 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2258 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2259 void *pvEncoded
, DWORD
*pcbEncoded
)
2263 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2265 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2266 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2267 pvEncoded
, pcbEncoded
);
2269 if (!pvEncoded
&& !pcbEncoded
)
2271 SetLastError(ERROR_INVALID_PARAMETER
);
2274 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2275 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2277 SetLastError(ERROR_FILE_NOT_FOUND
);
2281 SetLastError(NOERROR
);
2282 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2283 *(BYTE
**)pvEncoded
= NULL
;
2284 if (!HIWORD(lpszStructType
))
2286 switch (LOWORD(lpszStructType
))
2288 case (WORD
)X509_CERT
:
2289 encodeFunc
= CRYPT_AsnEncodeCert
;
2291 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2292 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2294 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2295 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2297 case (WORD
)X509_EXTENSIONS
:
2298 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2300 case (WORD
)X509_NAME
:
2301 encodeFunc
= CRYPT_AsnEncodeName
;
2303 case (WORD
)X509_PUBLIC_KEY_INFO
:
2304 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2306 case (WORD
)X509_ALTERNATE_NAME
:
2307 encodeFunc
= CRYPT_AsnEncodeAltName
;
2309 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2310 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2312 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2313 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2315 case (WORD
)X509_OCTET_STRING
:
2316 encodeFunc
= CRYPT_AsnEncodeOctets
;
2318 case (WORD
)X509_BITS
:
2319 case (WORD
)X509_KEY_USAGE
:
2320 encodeFunc
= CRYPT_AsnEncodeBits
;
2322 case (WORD
)X509_INTEGER
:
2323 encodeFunc
= CRYPT_AsnEncodeInt
;
2325 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2326 encodeFunc
= CRYPT_AsnEncodeInteger
;
2328 case (WORD
)X509_MULTI_BYTE_UINT
:
2329 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2331 case (WORD
)X509_ENUMERATED
:
2332 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2334 case (WORD
)X509_CHOICE_OF_TIME
:
2335 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2337 case (WORD
)X509_SEQUENCE_OF_ANY
:
2338 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2340 case (WORD
)PKCS_UTC_TIME
:
2341 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2344 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2347 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2348 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2349 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2350 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2351 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2352 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2353 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2354 encodeFunc
= CRYPT_AsnEncodeBits
;
2355 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2356 encodeFunc
= CRYPT_AsnEncodeOctets
;
2357 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2358 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2359 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2360 encodeFunc
= CRYPT_AsnEncodeAltName
;
2361 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2362 encodeFunc
= CRYPT_AsnEncodeAltName
;
2363 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2364 encodeFunc
= CRYPT_AsnEncodeAltName
;
2365 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2366 encodeFunc
= CRYPT_AsnEncodeAltName
;
2367 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2368 encodeFunc
= CRYPT_AsnEncodeAltName
;
2370 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2371 debugstr_a(lpszStructType
));
2373 encodeFunc
= (CryptEncodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2374 lpszStructType
, CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, &lib
);
2376 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2377 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2379 SetLastError(ERROR_FILE_NOT_FOUND
);
2385 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2386 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2387 DWORD
*pcbStructInfo
)
2391 CryptDecodeObjectFunc pCryptDecodeObject
;
2393 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2394 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2395 pvStructInfo
, pcbStructInfo
);
2397 if (!pvStructInfo
&& !pcbStructInfo
)
2399 SetLastError(ERROR_INVALID_PARAMETER
);
2403 /* Try registered DLL first.. */
2404 pCryptDecodeObject
=
2405 (CryptDecodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2406 lpszStructType
, CRYPT_OID_DECODE_OBJECT_FUNC
, &lib
);
2407 if (pCryptDecodeObject
)
2409 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2410 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2415 /* If not, use CryptDecodeObjectEx */
2416 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2417 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2422 /* Gets the number of length bytes from the given (leading) length byte */
2423 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2425 /* Helper function to get the encoded length of the data starting at pbEncoded,
2426 * where pbEncoded[0] is the tag. If the data are too short to contain a
2427 * length or if the length is too large for cbEncoded, sets an appropriate
2428 * error code and returns FALSE.
2430 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2437 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2440 else if (pbEncoded
[1] <= 0x7f)
2442 if (pbEncoded
[1] + 1 > cbEncoded
)
2444 SetLastError(CRYPT_E_ASN1_EOD
);
2449 *len
= pbEncoded
[1];
2455 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2457 if (lenLen
> sizeof(DWORD
) + 1)
2459 SetLastError(CRYPT_E_ASN1_LARGE
);
2462 else if (lenLen
+ 2 > cbEncoded
)
2464 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2475 out
|= *pbEncoded
++;
2477 if (out
+ lenLen
+ 1 > cbEncoded
)
2479 SetLastError(CRYPT_E_ASN1_EOD
);
2492 /* Helper function to check *pcbStructInfo, set it to the required size, and
2493 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2494 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2495 * pointer to the newly allocated memory.
2497 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2498 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2503 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2505 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2506 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2508 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2509 if (!*(BYTE
**)pvStructInfo
)
2512 *pcbStructInfo
= bytesNeeded
;
2514 else if (*pcbStructInfo
< bytesNeeded
)
2516 *pcbStructInfo
= bytesNeeded
;
2517 SetLastError(ERROR_MORE_DATA
);
2523 /* A few of the members need explanation:
2525 * A sequence is decoded into a struct. The offset member is the
2526 * offset of this item within that struct.
2528 * The decoder function to use. If this is NULL, then the member isn't
2529 * decoded, but minSize space is reserved for it.
2531 * The minimum amount of space occupied after decoding. You must set this.
2533 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2534 * minSize space is filled with 0 for this member. (Any other failure
2535 * results in CRYPT_AsnDecodeSequence failing.)
2536 * hasPointer, pointerOffset, minSize:
2537 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2538 * the offset within the (outer) struct of the data pointer (or to the
2539 * first data pointer, if more than one exist).
2541 * Used by CRYPT_AsnDecodeSequence, not for your use.
2543 struct AsnDecodeSequenceItem
2546 CryptDecodeObjectExFunc decodeFunc
;
2550 DWORD pointerOffset
;
2554 /* This decodes an arbitrary sequence into a contiguous block of memory
2555 * (basically, a struct.) Each element being decoded is described by a struct
2556 * AsnDecodeSequenceItem, see above.
2557 * startingPointer is an optional pointer to the first place where dynamic
2558 * data will be stored. If you know the starting offset, you may pass it
2559 * here. Otherwise, pass NULL, and one will be inferred from the items.
2560 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2561 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2563 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2564 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2565 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2566 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2570 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
2571 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2574 if (pbEncoded
[0] == ASN_SEQUENCE
)
2578 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2580 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2581 DWORD i
, bytesNeeded
= 0, minSize
= 0;
2584 ptr
= pbEncoded
+ 1 + lenBytes
;
2585 for (i
= 0; ret
&& i
< cItem
; i
++)
2589 minSize
+= items
[i
].minSize
;
2590 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2592 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2595 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2597 if (items
[i
].decodeFunc
)
2599 TRACE("sizing item %ld\n", i
);
2600 ret
= items
[i
].decodeFunc(dwCertEncodingType
, NULL
,
2601 ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2602 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2606 /* Account for alignment padding */
2607 bytesNeeded
+= items
[i
].size
;
2608 if (items
[i
].size
% sizeof(DWORD
))
2609 bytesNeeded
+= sizeof(DWORD
) -
2610 items
[i
].size
% sizeof(DWORD
);
2611 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2613 else if (items
[i
].optional
&&
2614 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2616 TRACE("skipping optional item %ld\n", i
);
2617 bytesNeeded
+= items
[i
].minSize
;
2618 SetLastError(NOERROR
);
2622 TRACE("item %ld failed: %08lx\n", i
,
2626 bytesNeeded
+= items
[i
].minSize
;
2629 else if (items
[i
].optional
)
2630 bytesNeeded
+= items
[i
].minSize
;
2633 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2637 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2639 TRACE("%ld remaining bytes, failing\n", cbEncoded
-
2641 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2647 *pcbStructInfo
= bytesNeeded
;
2648 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2649 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2653 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2654 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2655 if (startingPointer
)
2656 nextData
= (BYTE
*)startingPointer
;
2658 nextData
= (BYTE
*)pvStructInfo
+ minSize
;
2659 memset(pvStructInfo
, 0, minSize
);
2660 ptr
= pbEncoded
+ 1 + lenBytes
;
2661 for (i
= 0; ret
&& i
< cItem
; i
++)
2663 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2666 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2668 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2670 if (items
[i
].hasPointer
)
2672 *(BYTE
**)((BYTE
*)pvStructInfo
+
2673 items
[i
].pointerOffset
) = nextData
;
2675 if (items
[i
].decodeFunc
)
2677 TRACE("decoding item %ld\n", i
);
2678 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2679 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2680 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2681 (BYTE
*)pvStructInfo
+ items
[i
].offset
,
2684 TRACE("item %ld failed: %08lx\n", i
,
2688 items
[i
].size
= items
[i
].minSize
;
2691 if (items
[i
].hasPointer
&&
2692 items
[i
].size
> items
[i
].minSize
)
2694 nextData
+= items
[i
].size
-
2696 /* align nextData to DWORD boundaries */
2697 if (items
[i
].size
% sizeof(DWORD
))
2699 nextData
+= sizeof(DWORD
) -
2700 items
[i
].size
% sizeof(DWORD
);
2703 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2705 else if (items
[i
].optional
&&
2706 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2708 SetLastError(NOERROR
);
2712 else if (!items
[i
].optional
)
2714 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2724 SetLastError(CRYPT_E_ASN1_BADTAG
);
2727 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2731 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2732 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2733 * to CRYPT_E_ASN1_CORRUPT.
2734 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2737 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2738 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2739 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2744 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2746 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2747 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2749 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2750 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2753 *pcbStructInfo
= bytesNeeded
;
2754 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2755 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2757 CRYPT_DER_BLOB
*blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
2759 blob
->cbData
= 1 + lenBytes
+ dataLen
;
2762 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2763 blob
->pbData
= (BYTE
*)pbEncoded
;
2766 assert(blob
->pbData
);
2767 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
2772 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2780 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2781 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
2782 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2783 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2787 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
2788 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2790 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2793 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
2794 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
2795 pvStructInfo
, pcbStructInfo
);
2796 if (ret
&& pvStructInfo
)
2798 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2805 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2807 temp
= blob
->pbData
[i
];
2808 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2809 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2813 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2817 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
2818 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2819 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2823 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2824 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2828 struct AsnDecodeSequenceItem items
[] = {
2829 { offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
2830 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2831 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
2832 { offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
),
2833 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2834 FALSE
, TRUE
, offsetof(CERT_SIGNED_CONTENT_INFO
,
2835 SignatureAlgorithm
.pszObjId
), 0 },
2836 { offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
2837 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2838 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
2841 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
2842 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
2843 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2844 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2845 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2847 _SEH_EXCEPT(page_fault
)
2849 SetLastError(STATUS_ACCESS_VIOLATION
);
2856 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
2857 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2858 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2862 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
))
2866 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2868 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2870 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2871 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
2872 pvStructInfo
, pcbStructInfo
);
2877 SetLastError(CRYPT_E_ASN1_BADTAG
);
2883 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
2884 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2885 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2889 struct AsnDecodeSequenceItem items
[] = {
2890 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
2891 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2892 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
2893 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2896 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2897 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2898 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2902 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
2903 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2904 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2908 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3))
2912 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2914 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2916 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
2917 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
2918 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2923 SetLastError(CRYPT_E_ASN1_BADTAG
);
2929 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
2930 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2931 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2935 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2936 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2940 struct AsnDecodeSequenceItem items
[] = {
2941 { offsetof(CERT_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
2942 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
2943 { offsetof(CERT_INFO
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2944 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2945 SerialNumber
.pbData
), 0 },
2946 { offsetof(CERT_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
2947 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2948 SignatureAlgorithm
.pszObjId
), 0 },
2949 { offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
2950 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2952 { offsetof(CERT_INFO
, NotBefore
), CRYPT_AsnDecodeValidity
,
2953 sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
, FALSE
, 0 },
2954 { offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
2955 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2957 { offsetof(CERT_INFO
, SubjectPublicKeyInfo
), CRYPT_AsnDecodePubKeyInfo
,
2958 sizeof(CERT_PUBLIC_KEY_INFO
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2959 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
2960 { offsetof(CERT_INFO
, IssuerUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2961 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2962 IssuerUniqueId
.pbData
), 0 },
2963 { offsetof(CERT_INFO
, SubjectUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2964 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2965 SubjectUniqueId
.pbData
), 0 },
2966 { offsetof(CERT_INFO
, cExtension
), CRYPT_AsnDecodeCertExtensions
,
2967 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2971 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2972 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2973 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2975 _SEH_EXCEPT(page_fault
)
2977 SetLastError(STATUS_ACCESS_VIOLATION
);
2984 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2985 DWORD dwFlags
, PCRL_ENTRY entry
, DWORD
*pcbEntry
)
2988 struct AsnDecodeSequenceItem items
[] = {
2989 { offsetof(CRL_ENTRY
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2990 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CRL_ENTRY
,
2991 SerialNumber
.pbData
), 0 },
2992 { offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
2993 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2994 { offsetof(CRL_ENTRY
, cExtension
), CRYPT_AsnDecodeExtensionsInternal
,
2995 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CRL_ENTRY
,
2999 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
3002 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3003 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3004 NULL
, entry
, pcbEntry
, entry
? entry
->SerialNumber
.pbData
: NULL
);
3005 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3009 typedef struct _WINE_CRL_ENTRIES
{
3011 PCRL_ENTRY rgCRLEntry
;
3012 } WINE_CRL_ENTRIES
, *PWINE_CRL_ENTRIES
;
3014 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
3015 * been set prior to calling.
3017 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
3018 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3019 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3023 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3024 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3026 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3028 DWORD dataLen
, bytesNeeded
;
3030 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3032 DWORD cCRLEntry
= 0;
3033 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3035 bytesNeeded
= sizeof(WINE_CRL_ENTRIES
);
3041 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3042 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3045 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3046 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3052 bytesNeeded
+= size
;
3053 ret
= CRYPT_GetLen(ptr
,
3054 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3056 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3063 *pcbStructInfo
= bytesNeeded
;
3064 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3065 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3070 PWINE_CRL_ENTRIES entries
;
3072 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3073 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3074 *pcbStructInfo
= bytesNeeded
;
3075 entries
= (PWINE_CRL_ENTRIES
)pvStructInfo
;
3076 entries
->cCRLEntry
= cCRLEntry
;
3077 assert(entries
->rgCRLEntry
);
3078 nextData
= (BYTE
*)entries
->rgCRLEntry
+
3079 entries
->cCRLEntry
* sizeof(CRL_ENTRY
);
3080 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3081 i
< cCRLEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
3084 entries
->rgCRLEntry
[i
].SerialNumber
.pbData
= nextData
;
3086 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3087 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3088 &entries
->rgCRLEntry
[i
], &size
);
3093 bytesNeeded
-= size
;
3094 /* Increment nextData by the difference of the
3095 * minimum size and the actual size.
3097 if (size
> sizeof(CRL_ENTRY
))
3098 nextData
+= size
- sizeof(CRL_ENTRY
);
3099 ret
= CRYPT_GetLen(ptr
,
3100 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3102 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3111 SetLastError(CRYPT_E_ASN1_BADTAG
);
3114 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3118 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
3119 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3120 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3124 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3125 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3129 struct AsnDecodeSequenceItem items
[] = {
3130 { offsetof(CRL_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
3131 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3132 { offsetof(CRL_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
3133 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3134 SignatureAlgorithm
.pszObjId
), 0 },
3135 { offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3136 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3138 { offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3139 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3140 { offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3141 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
3142 { offsetof(CRL_INFO
, cCRLEntry
), CRYPT_AsnDecodeCRLEntries
,
3143 sizeof(WINE_CRL_ENTRIES
), TRUE
, TRUE
, offsetof(CRL_INFO
,
3145 /* Note that the extensions are ignored by MS, so I'll ignore them too
3147 { offsetof(CRL_INFO
, cExtension
), NULL
,
3148 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
3151 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3152 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3153 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3155 _SEH_EXCEPT(page_fault
)
3157 SetLastError(STATUS_ACCESS_VIOLATION
);
3162 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3166 /* Differences between this and CRYPT_AsnDecodeOid:
3167 * - pvStructInfo is a LPSTR *, not an LPSTR
3168 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3169 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3172 static BOOL WINAPI
CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType
,
3173 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3174 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3178 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3179 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3181 ret
= CRYPT_AsnDecodeOid(pbEncoded
, cbEncoded
, dwFlags
,
3182 pvStructInfo
? *(LPSTR
*)pvStructInfo
: NULL
, pcbStructInfo
);
3183 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
3184 *pcbStructInfo
+= sizeof(LPSTR
);
3185 if (ret
&& pvStructInfo
)
3186 TRACE("returning %s\n", debugstr_a(*(LPSTR
*)pvStructInfo
));
3190 /* Warning: assumes ext->pszObjId is set ahead of time! */
3191 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3192 DWORD dwFlags
, CERT_EXTENSION
*ext
, DWORD
*pcbExt
)
3194 struct AsnDecodeSequenceItem items
[] = {
3195 { offsetof(CERT_EXTENSION
, pszObjId
), CRYPT_AsnDecodeOidWrapper
,
3196 sizeof(LPSTR
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
, pszObjId
), 0 },
3197 { offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
3198 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
3199 { offsetof(CERT_EXTENSION
, Value
), CRYPT_AsnDecodeOctetsInternal
,
3200 sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
,
3205 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
3209 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
3210 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3211 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3212 ext
, pcbExt
, ext
? ext
->pszObjId
: NULL
);
3214 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
3215 debugstr_a(ext
->pszObjId
));
3216 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3220 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
3221 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3222 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3226 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3227 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3229 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3231 DWORD dataLen
, bytesNeeded
;
3233 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3235 DWORD cExtension
= 0;
3236 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3238 bytesNeeded
= sizeof(CERT_EXTENSIONS
);
3244 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3245 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3248 ret
= CRYPT_AsnDecodeExtension(ptr
,
3249 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3255 bytesNeeded
+= size
;
3256 ret
= CRYPT_GetLen(ptr
,
3257 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3259 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3266 *pcbStructInfo
= bytesNeeded
;
3267 else if (*pcbStructInfo
< bytesNeeded
)
3269 SetLastError(ERROR_MORE_DATA
);
3270 *pcbStructInfo
= bytesNeeded
;
3278 CERT_EXTENSIONS
*exts
;
3280 *pcbStructInfo
= bytesNeeded
;
3281 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3282 exts
->cExtension
= cExtension
;
3283 assert(exts
->rgExtension
);
3284 nextData
= (BYTE
*)exts
->rgExtension
+
3285 exts
->cExtension
* sizeof(CERT_EXTENSION
);
3286 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3287 i
< cExtension
&& ptr
- pbEncoded
- 1 - lenBytes
<
3290 exts
->rgExtension
[i
].pszObjId
= (LPSTR
)nextData
;
3292 ret
= CRYPT_AsnDecodeExtension(ptr
,
3293 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3294 &exts
->rgExtension
[i
], &size
);
3299 bytesNeeded
-= size
;
3300 if (size
> sizeof(CERT_EXTENSION
))
3301 nextData
+= size
- sizeof(CERT_EXTENSION
);
3302 ret
= CRYPT_GetLen(ptr
,
3303 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3305 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3314 SetLastError(CRYPT_E_ASN1_BADTAG
);
3320 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3321 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3322 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3328 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3329 lpszStructType
, pbEncoded
, cbEncoded
,
3330 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3331 if (ret
&& pvStructInfo
)
3333 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3334 pcbStructInfo
, *pcbStructInfo
);
3337 CERT_EXTENSIONS
*exts
;
3339 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3340 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3341 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3342 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3343 sizeof(CERT_EXTENSIONS
));
3344 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3345 lpszStructType
, pbEncoded
, cbEncoded
,
3346 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3351 _SEH_EXCEPT(page_fault
)
3353 SetLastError(STATUS_ACCESS_VIOLATION
);
3360 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3361 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3362 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
)
3366 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, pszObjId
,
3371 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3375 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3377 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3382 /* The largest possible string for the first two components
3383 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3388 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3389 pbEncoded
[1 + lenBytes
] / 40,
3390 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3392 bytesNeeded
= strlen(firstTwo
) + 1;
3393 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3394 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3396 /* large enough for ".4000000" */
3400 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3407 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3410 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3417 snprintf(str
, sizeof(str
), ".%d", val
);
3418 bytesNeeded
+= strlen(str
);
3422 *pcbObjId
= bytesNeeded
;
3423 else if (*pcbObjId
< bytesNeeded
)
3425 *pcbObjId
= bytesNeeded
;
3426 SetLastError(ERROR_MORE_DATA
);
3432 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3433 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3435 pszObjId
+= strlen(pszObjId
);
3436 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3437 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3441 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3450 sprintf(pszObjId
, ".%d", val
);
3451 pszObjId
+= strlen(pszObjId
);
3457 *pcbObjId
= bytesNeeded
;
3462 SetLastError(CRYPT_E_ASN1_BADTAG
);
3466 _SEH_EXCEPT(page_fault
)
3468 SetLastError(STATUS_ACCESS_VIOLATION
);
3475 /* Warning: this assumes the address of value->Value.pbData is already set, in
3476 * order to avoid overwriting memory. (In some cases, it may change it, if it
3477 * doesn't copy anything to memory.) Be sure to set it correctly!
3479 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(const BYTE
*pbEncoded
,
3480 DWORD cbEncoded
, DWORD dwFlags
, CERT_NAME_VALUE
*value
, DWORD
*pcbValue
)
3488 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3490 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3492 switch (pbEncoded
[0])
3494 case ASN_NUMERICSTRING
:
3495 case ASN_PRINTABLESTRING
:
3499 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3500 SetLastError(OSS_UNIMPLEMENTED
);
3505 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3507 switch (pbEncoded
[0])
3509 case ASN_NUMERICSTRING
:
3510 case ASN_PRINTABLESTRING
:
3512 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3513 bytesNeeded
+= dataLen
;
3517 *pcbValue
= bytesNeeded
;
3518 else if (*pcbValue
< bytesNeeded
)
3520 *pcbValue
= bytesNeeded
;
3521 SetLastError(ERROR_MORE_DATA
);
3526 *pcbValue
= bytesNeeded
;
3527 switch (pbEncoded
[0])
3529 case ASN_NUMERICSTRING
:
3530 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3532 case ASN_PRINTABLESTRING
:
3533 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3536 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3541 switch (pbEncoded
[0])
3543 case ASN_NUMERICSTRING
:
3544 case ASN_PRINTABLESTRING
:
3546 value
->Value
.cbData
= dataLen
;
3547 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3548 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3552 assert(value
->Value
.pbData
);
3553 memcpy(value
->Value
.pbData
,
3554 pbEncoded
+ 1 + lenBytes
, dataLen
);
3561 value
->Value
.cbData
= 0;
3562 value
->Value
.pbData
= NULL
;
3568 _SEH_EXCEPT(page_fault
)
3570 SetLastError(STATUS_ACCESS_VIOLATION
);
3577 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3578 * at the moment because of the ASN_CONSTRUCTOR tag.)
3580 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
,
3581 DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN_ATTR
*attr
, DWORD
*pcbAttr
)
3587 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
3589 DWORD bytesNeeded
, dataLen
, size
;
3592 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3594 /* The data length must be at least 4, two for the tag and
3595 * length for the OID, and two for the string (assuming both
3596 * have short-form lengths.)
3600 SetLastError(CRYPT_E_ASN1_EOD
);
3605 bytesNeeded
= sizeof(CERT_RDN_ATTR
);
3606 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3607 ret
= CRYPT_AsnDecodeOid(pbEncoded
+ 1 + lenBytes
,
3608 cbEncoded
- 1 - lenBytes
, dwFlags
, NULL
, &size
);
3611 /* ugly: need to know the size of the next element of
3612 * the sequence, so get it directly
3614 DWORD objIdOfset
= 1 + lenBytes
, objIdLen
,
3615 nameValueOffset
= 0;
3617 ret
= CRYPT_GetLen(pbEncoded
+ objIdOfset
,
3618 cbEncoded
- objIdOfset
, &objIdLen
);
3619 bytesNeeded
+= size
;
3620 /* hack: like encoding, this takes advantage of the
3621 * fact that the rest of the structure is identical to
3622 * a CERT_NAME_VALUE.
3626 nameValueOffset
= objIdOfset
+ objIdLen
+ 1 +
3627 GET_LEN_BYTES(pbEncoded
[objIdOfset
]);
3628 ret
= CRYPT_AsnDecodeNameValue(
3629 pbEncoded
+ nameValueOffset
,
3630 cbEncoded
- nameValueOffset
, dwFlags
, NULL
, &size
);
3634 bytesNeeded
+= size
;
3636 *pcbAttr
= bytesNeeded
;
3637 else if (*pcbAttr
< bytesNeeded
)
3639 *pcbAttr
= bytesNeeded
;
3640 SetLastError(ERROR_MORE_DATA
);
3645 BYTE
*originalData
= attr
->Value
.pbData
;
3647 *pcbAttr
= bytesNeeded
;
3648 /* strange: decode the value first, because it
3649 * has a counted size, and we can store the OID
3650 * after it. Keep track of the original data
3651 * pointer, we'll need to know whether it was
3655 ret
= CRYPT_AsnDecodeNameValue(
3656 pbEncoded
+ nameValueOffset
,
3657 cbEncoded
- nameValueOffset
, dwFlags
,
3658 (CERT_NAME_VALUE
*)&attr
->dwValueType
, &size
);
3663 /* if the data were copied to the
3664 * original location, the OID goes
3665 * after. Otherwise it goes in the
3666 * spot originally reserved for the
3669 if (attr
->Value
.pbData
== originalData
)
3671 (LPSTR
)(attr
->Value
.pbData
+
3672 attr
->Value
.cbData
);
3675 (LPSTR
)originalData
;
3676 size
= bytesNeeded
- size
;
3677 ret
= CRYPT_AsnDecodeOid(
3678 pbEncoded
+ objIdOfset
,
3679 cbEncoded
- objIdOfset
,
3680 dwFlags
, attr
->pszObjId
, &size
);
3683 attr
->pszObjId
= NULL
;
3693 SetLastError(CRYPT_E_ASN1_BADTAG
);
3697 _SEH_EXCEPT(page_fault
)
3699 SetLastError(STATUS_ACCESS_VIOLATION
);
3706 static BOOL WINAPI
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3707 DWORD dwFlags
, CERT_RDN
*rdn
, DWORD
*pcbRdn
)
3713 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SETOF
))
3717 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3719 DWORD bytesNeeded
, cRDNAttr
= 0;
3720 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3722 bytesNeeded
= sizeof(CERT_RDN
);
3728 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3729 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3731 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3732 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3738 bytesNeeded
+= size
;
3739 ret
= CRYPT_GetLen(ptr
,
3740 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3742 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3749 *pcbRdn
= bytesNeeded
;
3750 else if (*pcbRdn
< bytesNeeded
)
3752 *pcbRdn
= bytesNeeded
;
3753 SetLastError(ERROR_MORE_DATA
);
3762 *pcbRdn
= bytesNeeded
;
3763 rdn
->cRDNAttr
= cRDNAttr
;
3764 rdn
->rgRDNAttr
= (CERT_RDN_ATTR
*)((BYTE
*)rdn
+
3766 nextData
= (BYTE
*)rdn
->rgRDNAttr
+
3767 rdn
->cRDNAttr
* sizeof(CERT_RDN_ATTR
);
3768 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3769 i
< cRDNAttr
&& ptr
- pbEncoded
- 1 - lenBytes
<
3772 rdn
->rgRDNAttr
[i
].Value
.pbData
= nextData
;
3774 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3775 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3776 &rdn
->rgRDNAttr
[i
], &size
);
3781 bytesNeeded
-= size
;
3782 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3783 * data may not have been copied.
3785 if (rdn
->rgRDNAttr
[i
].Value
.pbData
== nextData
)
3787 rdn
->rgRDNAttr
[i
].Value
.cbData
;
3788 /* Ugly: the OID, if copied, is stored in
3789 * memory after the value, so increment by its
3790 * string length if it's set and points here.
3792 if ((const BYTE
*)rdn
->rgRDNAttr
[i
].pszObjId
3795 rdn
->rgRDNAttr
[i
].pszObjId
) + 1;
3796 ret
= CRYPT_GetLen(ptr
,
3797 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3799 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3808 SetLastError(CRYPT_E_ASN1_BADTAG
);
3812 _SEH_EXCEPT(page_fault
)
3814 SetLastError(STATUS_ACCESS_VIOLATION
);
3821 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3822 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3823 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3829 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCEOF
))
3833 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3835 DWORD bytesNeeded
, cRDN
= 0;
3836 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3838 bytesNeeded
= sizeof(CERT_NAME_INFO
);
3843 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3844 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3848 ret
= CRYPT_AsnDecodeRdn(ptr
,
3849 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3855 bytesNeeded
+= size
;
3856 ret
= CRYPT_GetLen(ptr
,
3857 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3859 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3866 *pcbStructInfo
= bytesNeeded
;
3867 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3868 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3870 CERT_NAME_INFO
*info
;
3872 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3873 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3874 info
= (CERT_NAME_INFO
*)pvStructInfo
;
3876 if (info
->cRDN
== 0)
3884 info
->rgRDN
= (CERT_RDN
*)((BYTE
*)pvStructInfo
+
3885 sizeof(CERT_NAME_INFO
));
3886 nextData
= (BYTE
*)info
->rgRDN
+
3887 info
->cRDN
* sizeof(CERT_RDN
);
3888 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3889 i
< cRDN
&& ptr
- pbEncoded
- 1 - lenBytes
<
3892 info
->rgRDN
[i
].rgRDNAttr
=
3893 (CERT_RDN_ATTR
*)nextData
;
3895 ret
= CRYPT_AsnDecodeRdn(ptr
,
3896 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3897 &info
->rgRDN
[i
], &size
);
3903 bytesNeeded
-= size
;
3904 ret
= CRYPT_GetLen(ptr
,
3905 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3907 ptr
+= nextLen
+ 1 +
3908 GET_LEN_BYTES(ptr
[1]);
3918 SetLastError(CRYPT_E_ASN1_BADTAG
);
3922 _SEH_EXCEPT(page_fault
)
3924 SetLastError(STATUS_ACCESS_VIOLATION
);
3931 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
3932 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3933 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3936 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
3938 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3939 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3941 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3942 bytesNeeded
+= cbEncoded
;
3944 *pcbStructInfo
= bytesNeeded
;
3945 else if (*pcbStructInfo
< bytesNeeded
)
3947 SetLastError(ERROR_MORE_DATA
);
3948 *pcbStructInfo
= bytesNeeded
;
3953 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
3955 *pcbStructInfo
= bytesNeeded
;
3956 blob
->cbData
= cbEncoded
;
3957 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3958 blob
->pbData
= (LPBYTE
)pbEncoded
;
3961 assert(blob
->pbData
);
3962 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3968 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3969 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3970 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3972 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3973 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3975 struct AsnDecodeSequenceItem items
[] = {
3976 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
3977 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3978 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
3979 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
3980 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
3981 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
3984 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3985 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3987 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3988 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3989 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
3990 if (ret
&& pvStructInfo
)
3992 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
3993 debugstr_a(algo
->pszObjId
));
3998 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
3999 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4000 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4006 struct AsnDecodeSequenceItem items
[] = {
4007 { offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
4008 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
4009 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
4010 Algorithm
.pszObjId
) },
4011 { offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
4012 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
4013 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
4016 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4017 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4018 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4020 _SEH_EXCEPT(page_fault
)
4022 SetLastError(STATUS_ACCESS_VIOLATION
);
4029 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
4030 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4031 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4037 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4040 if (pbEncoded
[0] != ASN_BOOL
)
4042 SetLastError(CRYPT_E_ASN1_BADTAG
);
4045 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
4047 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4050 if (pbEncoded
[1] > 1)
4052 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4057 *pcbStructInfo
= sizeof(BOOL
);
4060 else if (*pcbStructInfo
< sizeof(BOOL
))
4062 *pcbStructInfo
= sizeof(BOOL
);
4063 SetLastError(ERROR_MORE_DATA
);
4068 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
4071 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4075 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4076 DWORD dwFlags
, CERT_ALT_NAME_ENTRY
*entry
, DWORD
*pcbEntry
)
4078 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
4083 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4086 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
4088 SetLastError(CRYPT_E_ASN1_BADTAG
);
4091 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4092 if (1 + lenBytes
> cbEncoded
)
4094 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4097 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4099 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4101 case 1: /* rfc822Name */
4102 case 2: /* dNSName */
4103 case 6: /* uniformResourceIdentifier */
4104 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
4106 case 7: /* iPAddress */
4107 bytesNeeded
+= dataLen
;
4109 case 8: /* registeredID */
4110 /* FIXME: decode as OID */
4111 case 0: /* otherName */
4112 case 4: /* directoryName */
4114 SetLastError(CRYPT_E_ASN1_BADTAG
);
4117 case 3: /* x400Address, unimplemented */
4118 case 5: /* ediPartyName, unimplemented */
4119 SetLastError(CRYPT_E_ASN1_BADTAG
);
4123 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4129 *pcbEntry
= bytesNeeded
;
4130 else if (*pcbEntry
< bytesNeeded
)
4132 SetLastError(ERROR_MORE_DATA
);
4137 /* MS used values one greater than the asn1 ones.. sigh */
4138 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
4139 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4141 case 1: /* rfc822Name */
4142 case 2: /* dNSName */
4143 case 6: /* uniformResourceIdentifier */
4147 for (i
= 0; i
< dataLen
; i
++)
4149 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
4150 entry
->pwszURL
[i
] = 0;
4153 case 7: /* iPAddress */
4154 /* The next data pointer is in the pwszURL spot, that is,
4155 * the first 4 bytes. Need to move it to the next spot.
4157 entry
->IPAddress
.pbData
= (LPBYTE
)entry
->pwszURL
;
4158 entry
->IPAddress
.cbData
= dataLen
;
4159 memcpy(entry
->IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
4169 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
4170 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4171 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4177 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
4181 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4183 DWORD bytesNeeded
, cEntry
= 0;
4184 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4186 bytesNeeded
= sizeof(CERT_ALT_NAME_INFO
);
4191 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4192 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
4196 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4197 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
4203 bytesNeeded
+= size
;
4204 ret
= CRYPT_GetLen(ptr
,
4205 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4207 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
4214 *pcbStructInfo
= bytesNeeded
;
4215 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4216 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4218 CERT_ALT_NAME_INFO
*info
;
4220 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4221 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4222 info
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
4223 info
->cAltEntry
= 0;
4225 info
->rgAltEntry
= NULL
;
4233 (CERT_ALT_NAME_ENTRY
*)((BYTE
*)pvStructInfo
+
4234 sizeof(CERT_ALT_NAME_INFO
));
4235 nextData
= (BYTE
*)info
->rgAltEntry
+
4236 cEntry
* sizeof(CERT_ALT_NAME_ENTRY
);
4237 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4238 i
< cEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
4241 info
->rgAltEntry
[i
].pwszURL
=
4244 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4245 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
4246 &info
->rgAltEntry
[i
], &size
);
4253 sizeof(CERT_ALT_NAME_ENTRY
);
4254 bytesNeeded
-= size
;
4255 ret
= CRYPT_GetLen(ptr
,
4256 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4258 ptr
+= nextLen
+ 1 +
4259 GET_LEN_BYTES(ptr
[1]);
4269 SetLastError(CRYPT_E_ASN1_BADTAG
);
4273 _SEH_EXCEPT(page_fault
)
4275 SetLastError(STATUS_ACCESS_VIOLATION
);
4282 struct PATH_LEN_CONSTRAINT
4284 BOOL fPathLenConstraint
;
4285 DWORD dwPathLenConstraint
;
4288 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
4289 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4290 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4296 if (pbEncoded
[0] == ASN_INTEGER
)
4298 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
4301 *pcbStructInfo
= bytesNeeded
;
4302 else if (*pcbStructInfo
< bytesNeeded
)
4304 SetLastError(ERROR_MORE_DATA
);
4305 *pcbStructInfo
= bytesNeeded
;
4310 struct PATH_LEN_CONSTRAINT
*constraint
=
4311 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
4312 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
4314 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
4315 pbEncoded
, cbEncoded
, 0, NULL
,
4316 &constraint
->dwPathLenConstraint
, &size
);
4318 constraint
->fPathLenConstraint
= TRUE
;
4319 TRACE("got an int, dwPathLenConstraint is %ld\n",
4320 constraint
->dwPathLenConstraint
);
4325 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4329 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4333 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
4334 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4335 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4341 struct AsnDecodeSequenceItem items
[] = {
4342 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
), CRYPT_AsnDecodeBool
,
4343 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
4344 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fPathLenConstraint
),
4345 CRYPT_AsnDecodePathLenConstraint
, sizeof(struct PATH_LEN_CONSTRAINT
),
4346 TRUE
, FALSE
, 0, 0 },
4349 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4350 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4351 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4353 _SEH_EXCEPT(page_fault
)
4355 SetLastError(STATUS_ACCESS_VIOLATION
);
4362 #define RSA1_MAGIC 0x31415352
4364 struct DECODED_RSA_PUB_KEY
4367 CRYPT_INTEGER_BLOB modulus
;
4370 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4371 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4372 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4378 struct AsnDecodeSequenceItem items
[] = {
4379 { offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4380 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4381 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4383 { offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4384 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4386 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4389 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4390 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4391 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4394 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4395 decodedKey
->modulus
.cbData
;
4399 *pcbStructInfo
= bytesNeeded
;
4402 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4403 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4406 RSAPUBKEY
*rsaPubKey
;
4408 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4409 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4410 hdr
= (BLOBHEADER
*)pvStructInfo
;
4411 hdr
->bType
= PUBLICKEYBLOB
;
4412 hdr
->bVersion
= CUR_BLOB_VERSION
;
4414 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4415 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4416 sizeof(BLOBHEADER
));
4417 rsaPubKey
->magic
= RSA1_MAGIC
;
4418 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4419 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4420 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4421 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4422 decodedKey
->modulus
.cbData
);
4424 LocalFree(decodedKey
);
4427 _SEH_EXCEPT(page_fault
)
4429 SetLastError(STATUS_ACCESS_VIOLATION
);
4436 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
4437 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4438 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4442 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4443 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4445 if (pbEncoded
[0] == ASN_OCTETSTRING
)
4447 DWORD bytesNeeded
, dataLen
;
4449 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4451 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4452 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4454 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4456 *pcbStructInfo
= bytesNeeded
;
4457 else if (*pcbStructInfo
< bytesNeeded
)
4459 SetLastError(ERROR_MORE_DATA
);
4460 *pcbStructInfo
= bytesNeeded
;
4465 CRYPT_DATA_BLOB
*blob
;
4466 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4468 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4469 blob
->cbData
= dataLen
;
4470 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4471 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4474 assert(blob
->pbData
);
4476 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4484 SetLastError(CRYPT_E_ASN1_BADTAG
);
4490 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4491 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4492 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4496 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4497 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4503 if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4504 lpszStructType
, pbEncoded
, cbEncoded
,
4505 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4508 *pcbStructInfo
= bytesNeeded
;
4509 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4510 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4512 CRYPT_DATA_BLOB
*blob
;
4514 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4515 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4516 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4517 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
4518 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4519 lpszStructType
, pbEncoded
, cbEncoded
,
4520 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4526 SetLastError(CRYPT_E_ASN1_BADTAG
);
4530 _SEH_EXCEPT(page_fault
)
4532 SetLastError(STATUS_ACCESS_VIOLATION
);
4539 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4540 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4541 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4545 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4546 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4548 if (pbEncoded
[0] == ASN_BITSTRING
)
4550 DWORD bytesNeeded
, dataLen
;
4552 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4554 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4555 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4557 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4559 *pcbStructInfo
= bytesNeeded
;
4560 else if (*pcbStructInfo
< bytesNeeded
)
4562 *pcbStructInfo
= bytesNeeded
;
4563 SetLastError(ERROR_MORE_DATA
);
4568 CRYPT_BIT_BLOB
*blob
;
4570 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4571 blob
->cbData
= dataLen
- 1;
4572 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4573 GET_LEN_BYTES(pbEncoded
[1]));
4574 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4576 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4577 GET_LEN_BYTES(pbEncoded
[1]);
4581 assert(blob
->pbData
);
4584 BYTE mask
= 0xff << blob
->cUnusedBits
;
4586 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4587 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4588 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4596 SetLastError(CRYPT_E_ASN1_BADTAG
);
4599 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4603 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4604 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4605 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4609 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4610 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4616 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4617 lpszStructType
, pbEncoded
, cbEncoded
,
4618 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4621 *pcbStructInfo
= bytesNeeded
;
4622 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4623 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4625 CRYPT_BIT_BLOB
*blob
;
4627 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4628 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4629 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4630 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4631 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4632 lpszStructType
, pbEncoded
, cbEncoded
,
4633 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4638 _SEH_EXCEPT(page_fault
)
4640 SetLastError(STATUS_ACCESS_VIOLATION
);
4644 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4648 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4649 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4650 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4656 *pcbStructInfo
= sizeof(int);
4661 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4662 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4663 DWORD size
= sizeof(buf
);
4665 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4666 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4667 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4670 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4671 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4675 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4676 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4677 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4679 /* initialize to a negative value to sign-extend */
4684 for (i
= 0; i
< blob
->cbData
; i
++)
4687 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4689 memcpy(pvStructInfo
, &val
, sizeof(int));
4692 else if (GetLastError() == ERROR_MORE_DATA
)
4693 SetLastError(CRYPT_E_ASN1_LARGE
);
4695 _SEH_EXCEPT(page_fault
)
4697 SetLastError(STATUS_ACCESS_VIOLATION
);
4704 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4705 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4706 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4710 if (pbEncoded
[0] == ASN_INTEGER
)
4712 DWORD bytesNeeded
, dataLen
;
4714 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4716 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4718 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4720 *pcbStructInfo
= bytesNeeded
;
4721 else if (*pcbStructInfo
< bytesNeeded
)
4723 *pcbStructInfo
= bytesNeeded
;
4724 SetLastError(ERROR_MORE_DATA
);
4729 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4731 blob
->cbData
= dataLen
;
4732 assert(blob
->pbData
);
4737 for (i
= 0; i
< blob
->cbData
; i
++)
4739 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4748 SetLastError(CRYPT_E_ASN1_BADTAG
);
4754 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4755 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4756 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4764 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4765 lpszStructType
, pbEncoded
, cbEncoded
,
4766 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4769 *pcbStructInfo
= bytesNeeded
;
4770 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4771 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4773 CRYPT_INTEGER_BLOB
*blob
;
4775 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4776 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4777 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4778 blob
->pbData
= (BYTE
*)pvStructInfo
+
4779 sizeof(CRYPT_INTEGER_BLOB
);
4780 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4781 lpszStructType
, pbEncoded
, cbEncoded
,
4782 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4787 _SEH_EXCEPT(page_fault
)
4789 SetLastError(STATUS_ACCESS_VIOLATION
);
4796 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
4797 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
4798 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4799 void *pvStructInfo
, DWORD
*pcbStructInfo
)
4803 if (pbEncoded
[0] == ASN_INTEGER
)
4805 DWORD bytesNeeded
, dataLen
;
4807 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4809 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4811 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4813 *pcbStructInfo
= bytesNeeded
;
4814 else if (*pcbStructInfo
< bytesNeeded
)
4816 *pcbStructInfo
= bytesNeeded
;
4817 SetLastError(ERROR_MORE_DATA
);
4822 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4824 blob
->cbData
= dataLen
;
4825 assert(blob
->pbData
);
4826 /* remove leading zero byte if it exists */
4827 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4836 for (i
= 0; i
< blob
->cbData
; i
++)
4838 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4847 SetLastError(CRYPT_E_ASN1_BADTAG
);
4853 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4854 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4855 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4863 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4864 lpszStructType
, pbEncoded
, cbEncoded
,
4865 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4868 *pcbStructInfo
= bytesNeeded
;
4869 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4870 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4872 CRYPT_INTEGER_BLOB
*blob
;
4874 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4875 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4876 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4877 blob
->pbData
= (BYTE
*)pvStructInfo
+
4878 sizeof(CRYPT_INTEGER_BLOB
);
4879 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4880 lpszStructType
, pbEncoded
, cbEncoded
,
4881 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4886 _SEH_EXCEPT(page_fault
)
4888 SetLastError(STATUS_ACCESS_VIOLATION
);
4895 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4896 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4897 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4903 *pcbStructInfo
= sizeof(int);
4908 if (pbEncoded
[0] == ASN_ENUMERATED
)
4910 unsigned int val
= 0, i
;
4914 SetLastError(CRYPT_E_ASN1_EOD
);
4917 else if (pbEncoded
[1] == 0)
4919 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4924 /* A little strange looking, but we have to accept a sign byte:
4925 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4926 * assuming a small length is okay here, it has to be in short
4929 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4931 SetLastError(CRYPT_E_ASN1_LARGE
);
4934 for (i
= 0; i
< pbEncoded
[1]; i
++)
4937 val
|= pbEncoded
[2 + i
];
4939 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4940 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4942 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4943 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4944 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4950 SetLastError(CRYPT_E_ASN1_BADTAG
);
4954 _SEH_EXCEPT(page_fault
)
4956 SetLastError(STATUS_ACCESS_VIOLATION
);
4963 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4966 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4971 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4973 if (!isdigit(*(pbEncoded))) \
4975 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4981 (word) += *(pbEncoded)++ - '0'; \
4986 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
4987 SYSTEMTIME
*sysTime
)
4994 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
4996 WORD hours
, minutes
= 0;
4997 BYTE sign
= *pbEncoded
++;
5000 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
5001 if (ret
&& hours
>= 24)
5003 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5008 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
5009 if (ret
&& minutes
>= 60)
5011 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5019 sysTime
->wHour
+= hours
;
5020 sysTime
->wMinute
+= minutes
;
5024 if (hours
> sysTime
->wHour
)
5027 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
5030 sysTime
->wHour
-= hours
;
5031 if (minutes
> sysTime
->wMinute
)
5034 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
5037 sysTime
->wMinute
-= minutes
;
5042 _SEH_EXCEPT(page_fault
)
5044 SetLastError(STATUS_ACCESS_VIOLATION
);
5051 #define MIN_ENCODED_TIME_LENGTH 10
5053 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
5054 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5055 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5061 *pcbStructInfo
= sizeof(FILETIME
);
5067 if (pbEncoded
[0] == ASN_UTCTIME
)
5071 SetLastError(CRYPT_E_ASN1_EOD
);
5074 else if (pbEncoded
[1] > 0x7f)
5076 /* long-form date strings really can't be valid */
5077 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5082 SYSTEMTIME sysTime
= { 0 };
5083 BYTE len
= pbEncoded
[1];
5085 if (len
< MIN_ENCODED_TIME_LENGTH
)
5087 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5093 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
5094 if (sysTime
.wYear
>= 50)
5095 sysTime
.wYear
+= 1900;
5097 sysTime
.wYear
+= 2000;
5098 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5099 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5100 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5101 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
5104 if (len
>= 2 && isdigit(*pbEncoded
) &&
5105 isdigit(*(pbEncoded
+ 1)))
5106 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5108 else if (isdigit(*pbEncoded
))
5109 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
5112 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5115 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5116 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5119 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5120 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5121 ret
= SystemTimeToFileTime(&sysTime
,
5122 (FILETIME
*)pvStructInfo
);
5129 SetLastError(CRYPT_E_ASN1_BADTAG
);
5133 _SEH_EXCEPT(page_fault
)
5135 SetLastError(STATUS_ACCESS_VIOLATION
);
5142 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
5143 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5144 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5150 *pcbStructInfo
= sizeof(FILETIME
);
5156 if (pbEncoded
[0] == ASN_GENERALTIME
)
5160 SetLastError(CRYPT_E_ASN1_EOD
);
5163 else if (pbEncoded
[1] > 0x7f)
5165 /* long-form date strings really can't be valid */
5166 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5171 BYTE len
= pbEncoded
[1];
5173 if (len
< MIN_ENCODED_TIME_LENGTH
)
5175 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5180 SYSTEMTIME sysTime
= { 0 };
5183 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
5184 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5185 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5186 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5189 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5192 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5194 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
5201 /* workaround macro weirdness */
5202 digits
= min(len
, 3);
5203 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
5204 sysTime
.wMilliseconds
);
5207 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5210 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5211 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5214 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5215 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5216 ret
= SystemTimeToFileTime(&sysTime
,
5217 (FILETIME
*)pvStructInfo
);
5224 SetLastError(CRYPT_E_ASN1_BADTAG
);
5228 _SEH_EXCEPT(page_fault
)
5230 SetLastError(STATUS_ACCESS_VIOLATION
);
5237 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5238 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5239 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5245 if (pbEncoded
[0] == ASN_UTCTIME
)
5246 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5247 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5249 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5250 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5251 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5252 pvStructInfo
, pcbStructInfo
);
5255 SetLastError(CRYPT_E_ASN1_BADTAG
);
5259 _SEH_EXCEPT(page_fault
)
5261 SetLastError(STATUS_ACCESS_VIOLATION
);
5268 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5269 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5270 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5276 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5278 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5280 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5285 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5286 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5288 ptr
= pbEncoded
+ 1 + lenBytes
;
5289 remainingLen
= dataLen
;
5290 while (ret
&& remainingLen
)
5294 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5297 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5299 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5300 ptr
+= 1 + nextLenBytes
+ nextLen
;
5301 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5302 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5303 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5309 CRYPT_SEQUENCE_OF_ANY
*seq
;
5313 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5314 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5316 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5317 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5318 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5319 seq
->cValue
= cValue
;
5320 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5322 nextPtr
= (BYTE
*)seq
->rgValue
+
5323 cValue
* sizeof(CRYPT_DER_BLOB
);
5324 ptr
= pbEncoded
+ 1 + lenBytes
;
5325 remainingLen
= dataLen
;
5327 while (ret
&& remainingLen
)
5331 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5334 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5336 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5338 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5339 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5342 seq
->rgValue
[i
].pbData
= nextPtr
;
5343 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5345 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5347 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5348 ptr
+= 1 + nextLenBytes
+ nextLen
;
5358 SetLastError(CRYPT_E_ASN1_BADTAG
);
5362 _SEH_EXCEPT(page_fault
)
5364 SetLastError(STATUS_ACCESS_VIOLATION
);
5371 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5372 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5373 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5377 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5379 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5380 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5381 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5383 if (!pvStructInfo
&& !pcbStructInfo
)
5385 SetLastError(ERROR_INVALID_PARAMETER
);
5388 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5389 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5391 SetLastError(ERROR_FILE_NOT_FOUND
);
5396 SetLastError(CRYPT_E_ASN1_EOD
);
5399 if (cbEncoded
> MAX_ENCODED_LEN
)
5401 SetLastError(CRYPT_E_ASN1_LARGE
);
5405 SetLastError(NOERROR
);
5406 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5407 *(BYTE
**)pvStructInfo
= NULL
;
5408 if (!HIWORD(lpszStructType
))
5410 switch (LOWORD(lpszStructType
))
5412 case (WORD
)X509_CERT
:
5413 decodeFunc
= CRYPT_AsnDecodeCert
;
5415 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5416 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5418 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5419 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5421 case (WORD
)X509_EXTENSIONS
:
5422 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5424 case (WORD
)X509_NAME
:
5425 decodeFunc
= CRYPT_AsnDecodeName
;
5427 case (WORD
)X509_PUBLIC_KEY_INFO
:
5428 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5430 case (WORD
)X509_ALTERNATE_NAME
:
5431 decodeFunc
= CRYPT_AsnDecodeAltName
;
5433 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5434 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5436 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5437 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5439 case (WORD
)X509_OCTET_STRING
:
5440 decodeFunc
= CRYPT_AsnDecodeOctets
;
5442 case (WORD
)X509_BITS
:
5443 case (WORD
)X509_KEY_USAGE
:
5444 decodeFunc
= CRYPT_AsnDecodeBits
;
5446 case (WORD
)X509_INTEGER
:
5447 decodeFunc
= CRYPT_AsnDecodeInt
;
5449 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5450 decodeFunc
= CRYPT_AsnDecodeInteger
;
5452 case (WORD
)X509_MULTI_BYTE_UINT
:
5453 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5455 case (WORD
)X509_ENUMERATED
:
5456 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5458 case (WORD
)X509_CHOICE_OF_TIME
:
5459 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5461 case (WORD
)X509_SEQUENCE_OF_ANY
:
5462 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5464 case (WORD
)PKCS_UTC_TIME
:
5465 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5468 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5471 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5472 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5473 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5474 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5475 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5476 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5477 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5478 decodeFunc
= CRYPT_AsnDecodeBits
;
5479 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5480 decodeFunc
= CRYPT_AsnDecodeOctets
;
5481 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5482 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5483 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5484 decodeFunc
= CRYPT_AsnDecodeAltName
;
5485 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5486 decodeFunc
= CRYPT_AsnDecodeAltName
;
5487 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5488 decodeFunc
= CRYPT_AsnDecodeAltName
;
5489 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5490 decodeFunc
= CRYPT_AsnDecodeAltName
;
5491 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5492 decodeFunc
= CRYPT_AsnDecodeAltName
;
5494 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5495 debugstr_a(lpszStructType
));
5497 decodeFunc
= (CryptDecodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
5498 lpszStructType
, CRYPT_OID_DECODE_OBJECT_EX_FUNC
, &lib
);
5500 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5501 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5503 SetLastError(ERROR_FILE_NOT_FOUND
);
5509 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5510 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5512 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5513 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5516 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5517 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5518 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5523 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5524 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5527 if (!pszPublicKeyObjId
)
5528 pszPublicKeyObjId
= szOID_RSA_RSA
;
5529 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5533 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5536 LPBYTE pubKey
= CryptMemAlloc(keySize
);
5540 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
5544 DWORD encodedLen
= 0;
5546 ret
= CryptEncodeObject(dwCertEncodingType
,
5547 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5550 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5551 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5554 *pcbInfo
= sizeNeeded
;
5555 else if (*pcbInfo
< sizeNeeded
)
5557 SetLastError(ERROR_MORE_DATA
);
5558 *pcbInfo
= sizeNeeded
;
5563 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5564 sizeof(CERT_PUBLIC_KEY_INFO
);
5565 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5567 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5568 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5569 pInfo
->PublicKey
.pbData
=
5570 (BYTE
*)pInfo
->Algorithm
.pszObjId
5571 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5572 pInfo
->PublicKey
.cbData
= encodedLen
;
5573 pInfo
->PublicKey
.cUnusedBits
= 0;
5574 ret
= CryptEncodeObject(dwCertEncodingType
,
5575 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5576 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5580 CryptMemFree(pubKey
);
5585 CryptDestroyKey(key
);
5590 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5591 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5592 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5594 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5595 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5596 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5599 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5602 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5603 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5608 SetLastError(ERROR_INVALID_PARAMETER
);
5612 if (pszPublicKeyObjId
)
5613 exportFunc
= CRYPT_GetFunc(dwCertEncodingType
, pszPublicKeyObjId
,
5614 CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
, &lib
);
5616 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
5617 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5618 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5624 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5625 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5627 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5631 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5632 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5633 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5636 DWORD pubKeySize
= 0;
5638 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5639 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5641 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5642 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5645 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
5649 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5650 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5653 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5655 CryptMemFree(pubKey
);
5663 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5664 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5665 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5667 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5668 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5669 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5672 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5675 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5676 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5678 importFunc
= CRYPT_GetFunc(dwCertEncodingType
, pInfo
->Algorithm
.pszObjId
,
5679 CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, &lib
);
5681 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
5682 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,