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 /* This is a bit arbitrary, but to set some limit: */
38 #define MAX_ENCODED_LEN 0x02000000
40 /* a few asn.1 tags we need */
41 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
42 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
43 #define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
44 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
45 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
46 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
47 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
48 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
49 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
50 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
52 #define ASN_FLAGS_MASK 0xf0
53 #define ASN_TYPE_MASK 0x0f
55 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
57 static const WCHAR szDllName
[] = { 'D','l','l',0 };
59 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
61 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
62 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
63 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
64 DWORD
, DWORD
, void *, DWORD
*);
65 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
66 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
68 /* Prototypes for built-in encoders/decoders. They follow the Ex style
69 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
70 * built-in functions, but the parameters are retained to simplify
71 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
72 * external DLLs that follow these signatures.
73 * FIXME: some built-in functions are suitable to be called directly by
74 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
75 * and memory allocation if requested), others are only suitable to be called
76 * internally. Comment which are which.
78 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
80 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
81 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
82 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
83 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
84 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
86 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
87 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
89 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
90 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
91 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
92 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
93 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
95 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
96 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
97 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
98 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
99 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
100 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
101 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
102 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
103 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
104 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
105 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
106 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
107 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
108 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
109 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
110 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
112 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
113 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
114 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
115 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
116 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
117 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
118 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
119 * time, doesn't do memory allocation, and doesn't do exception handling.
120 * (This isn't intended to be the externally-called one.)
122 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
123 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
124 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
125 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
126 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
);
127 /* Assumes algo->Parameters.pbData is set ahead of time */
128 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
129 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
130 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
131 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
132 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
133 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
134 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
135 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
136 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
137 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
138 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
139 * member has been initialized, doesn't do exception handling, and doesn't do
142 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
143 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
144 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
145 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
146 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
147 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
148 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
149 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
150 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
151 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
152 * member has been initialized, doesn't do exception handling, and doesn't do
155 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(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 unsigned. */
159 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
160 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
161 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
162 void *pvStructInfo
, DWORD
*pcbStructInfo
);
164 /* filter for page-fault exceptions */
165 static WINE_EXCEPTION_FILTER(page_fault
)
167 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
168 return EXCEPTION_EXECUTE_HANDLER
;
169 return EXCEPTION_CONTINUE_SEARCH
;
172 static char *CRYPT_GetKeyName(DWORD dwEncodingType
, LPCSTR pszFuncName
,
175 static const char szEncodingTypeFmt
[] =
176 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
178 char numericOID
[7]; /* enough for "#65535" */
182 /* MSDN says the encoding type is a mask, but it isn't treated that way.
183 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
184 * "EncodingType 2" would be expected if it were a mask. Instead native
185 * stores values in "EncodingType 3".
189 snprintf(numericOID
, sizeof(numericOID
), "#%d", LOWORD(pszOID
));
195 /* This is enough: the lengths of the two string parameters are explicitly
196 * counted, and we need up to five additional characters for the encoding
197 * type. These are covered by the "%d", "%s", and "%s" characters in the
198 * format specifier that are removed by sprintf.
200 len
= sizeof(szEncodingTypeFmt
) + lstrlenA(pszFuncName
) + lstrlenA(oid
);
201 szKey
= CryptMemAlloc(len
);
203 sprintf(szKey
, szEncodingTypeFmt
, dwEncodingType
, pszFuncName
, oid
);
207 BOOL WINAPI
CryptRegisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
208 LPCSTR pszOID
, LPCWSTR pwszDll
, LPCSTR pszOverrideFuncName
)
214 TRACE("%lx %s %s %s %s\n", dwEncodingType
, pszFuncName
, pszOID
,
215 debugstr_w(pwszDll
), pszOverrideFuncName
);
217 /* This only registers functions for encoding certs, not messages */
218 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
221 /* Native does nothing pwszDll is NULL */
225 /* I'm not matching MS bug for bug here, because I doubt any app depends on
227 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
228 * it creates would never be used
229 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
230 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
232 if (!pszFuncName
|| !pszOID
)
234 SetLastError(ERROR_INVALID_PARAMETER
);
238 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
239 TRACE("Key name is %s\n", debugstr_a(szKey
));
244 r
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
246 if(r
!= ERROR_SUCCESS
)
249 /* write the values */
250 if (pszOverrideFuncName
)
251 RegSetValueExA(hKey
, "FuncName", 0, REG_SZ
, (const BYTE
*)pszOverrideFuncName
,
252 lstrlenA(pszOverrideFuncName
) + 1);
253 RegSetValueExW(hKey
, szDllName
, 0, REG_SZ
, (const BYTE
*) pwszDll
,
254 (lstrlenW(pwszDll
) + 1) * sizeof (WCHAR
));
260 BOOL WINAPI
CryptUnregisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
266 TRACE("%lx %s %s\n", dwEncodingType
, pszFuncName
, pszOID
);
268 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
271 if (!pszFuncName
|| !pszOID
)
273 SetLastError(ERROR_INVALID_PARAMETER
);
277 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
278 rc
= RegDeleteKeyA(HKEY_LOCAL_MACHINE
, szKey
);
282 return rc
? FALSE
: TRUE
;
285 BOOL WINAPI
CryptGetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
286 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD
*pdwValueType
, BYTE
*pbValueData
,
293 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType
, debugstr_a(pszFuncName
),
294 debugstr_a(pszOID
), debugstr_w(pwszValueName
), pdwValueType
, pbValueData
,
297 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
300 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
302 SetLastError(ERROR_INVALID_PARAMETER
);
306 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
307 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
313 rc
= RegQueryValueExW(hKey
, pwszValueName
, NULL
, pdwValueType
,
314 pbValueData
, pcbValueData
);
319 return rc
? FALSE
: TRUE
;
322 BOOL WINAPI
CryptSetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
323 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD dwValueType
,
324 const BYTE
*pbValueData
, DWORD cbValueData
)
330 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType
, debugstr_a(pszFuncName
),
331 debugstr_a(pszOID
), debugstr_w(pwszValueName
), dwValueType
, pbValueData
,
334 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
337 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
339 SetLastError(ERROR_INVALID_PARAMETER
);
343 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
344 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
350 rc
= RegSetValueExW(hKey
, pwszValueName
, 0, dwValueType
, pbValueData
,
356 return rc
? FALSE
: TRUE
;
359 /* Gets the registered function named szFuncName for dwCertEncodingType and
360 * lpszStructType, or NULL if one could not be found. *lib will be set to the
361 * handle of the module it's in, or NULL if no module was loaded. If the
362 * return value is NULL, *lib will also be NULL, to simplify error handling.
364 static void *CRYPT_GetFunc(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
365 LPCSTR szFuncName
, HMODULE
*lib
)
368 char *szKey
= CRYPT_GetKeyName(dwCertEncodingType
, szFuncName
,
370 const char *funcName
;
373 DWORD type
, size
= 0;
375 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType
, debugstr_a(lpszStructType
),
376 debugstr_a(szFuncName
), lib
);
379 r
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
381 if(r
!= ERROR_SUCCESS
)
384 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, NULL
, &size
);
385 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
387 funcName
= CryptMemAlloc(size
);
388 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, (LPBYTE
)funcName
,
392 funcName
= szFuncName
;
393 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, NULL
, &size
);
394 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
396 LPWSTR dllName
= CryptMemAlloc(size
);
398 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, (LPBYTE
)dllName
,
400 *lib
= LoadLibraryW(dllName
);
403 ret
= GetProcAddress(*lib
, funcName
);
406 /* Unload the library, the caller doesn't want to unload it
407 * when the return value is NULL.
413 CryptMemFree(dllName
);
415 if (funcName
!= szFuncName
)
416 CryptMemFree((char *)funcName
);
417 TRACE("returning %p\n", ret
);
421 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
422 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
426 CryptEncodeObjectFunc pCryptEncodeObject
;
428 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
429 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
432 if (!pbEncoded
&& !pcbEncoded
)
434 SetLastError(ERROR_INVALID_PARAMETER
);
438 /* Try registered DLL first.. */
440 (CryptEncodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
441 lpszStructType
, CRYPT_OID_ENCODE_OBJECT_FUNC
, &lib
);
442 if (pCryptEncodeObject
)
444 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
445 pvStructInfo
, pbEncoded
, pcbEncoded
);
450 /* If not, use CryptEncodeObjectEx */
451 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
452 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
457 /* Helper function to check *pcbEncoded, set it to the required size, and
458 * optionally to allocate memory. Assumes pbEncoded is not NULL.
459 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
460 * pointer to the newly allocated memory.
462 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
463 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
468 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
470 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
471 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
473 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
474 if (!*(BYTE
**)pbEncoded
)
477 *pcbEncoded
= bytesNeeded
;
479 else if (bytesNeeded
> *pcbEncoded
)
481 *pcbEncoded
= bytesNeeded
;
482 SetLastError(ERROR_MORE_DATA
);
488 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
490 DWORD bytesNeeded
, significantBytes
= 0;
498 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
499 temp
<<= 8, significantBytes
--)
501 bytesNeeded
= significantBytes
+ 1;
505 *pcbEncoded
= bytesNeeded
;
508 if (*pcbEncoded
< bytesNeeded
)
510 SetLastError(ERROR_MORE_DATA
);
514 *pbEncoded
= (BYTE
)len
;
519 *pbEncoded
++ = significantBytes
| 0x80;
520 for (i
= 0; i
< significantBytes
; i
++)
522 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
526 *pcbEncoded
= bytesNeeded
;
530 struct AsnEncodeSequenceItem
532 const void *pvStructInfo
;
533 CryptEncodeObjectExFunc encodeFunc
;
534 DWORD size
; /* used during encoding, not for your use */
537 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
538 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
539 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
542 DWORD i
, dataLen
= 0;
544 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
545 pbEncoded
, *pcbEncoded
);
546 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
548 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
549 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
550 NULL
, &items
[i
].size
);
551 dataLen
+= items
[i
].size
;
555 DWORD lenBytes
, bytesNeeded
;
557 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
558 bytesNeeded
= 1 + lenBytes
+ dataLen
;
560 *pcbEncoded
= bytesNeeded
;
563 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
564 pcbEncoded
, bytesNeeded
)))
566 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
567 pbEncoded
= *(BYTE
**)pbEncoded
;
568 *pbEncoded
++ = ASN_SEQUENCE
;
569 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
570 pbEncoded
+= lenBytes
;
571 for (i
= 0; ret
&& i
< cItem
; i
++)
573 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
574 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
575 NULL
, pbEncoded
, &items
[i
].size
);
576 pbEncoded
+= items
[i
].size
;
581 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
585 struct AsnConstructedItem
588 const void *pvStructInfo
;
589 CryptEncodeObjectExFunc encodeFunc
;
592 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
593 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
594 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
597 const struct AsnConstructedItem
*item
=
598 (const struct AsnConstructedItem
*)pvStructInfo
;
601 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
602 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
604 DWORD dataLen
, bytesNeeded
;
606 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
607 bytesNeeded
= 1 + dataLen
+ len
;
609 *pcbEncoded
= bytesNeeded
;
610 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
611 pbEncoded
, pcbEncoded
, bytesNeeded
)))
613 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
614 pbEncoded
= *(BYTE
**)pbEncoded
;
615 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
616 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
617 pbEncoded
+= dataLen
;
618 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
619 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
626 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
627 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
628 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
630 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
633 /* CERT_V1 is not encoded */
641 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
643 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
644 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
649 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
650 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
651 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
653 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
658 *pcbEncoded
= blob
->cbData
;
661 else if (*pcbEncoded
< blob
->cbData
)
663 *pcbEncoded
= blob
->cbData
;
664 SetLastError(ERROR_MORE_DATA
);
670 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
671 *pcbEncoded
= blob
->cbData
;
677 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
678 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
679 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
682 /* This has two filetimes in a row, a NotBefore and a NotAfter */
683 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
684 struct AsnEncodeSequenceItem items
[] = {
685 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
686 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
689 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
690 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
695 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
696 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
697 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
700 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
701 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
703 struct AsnEncodeSequenceItem items
[] = {
704 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
705 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
708 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
709 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
714 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
715 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
716 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
722 const CERT_PUBLIC_KEY_INFO
*info
=
723 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
724 struct AsnEncodeSequenceItem items
[] = {
725 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
726 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
729 TRACE("Encoding public key with OID %s\n",
730 debugstr_a(info
->Algorithm
.pszObjId
));
731 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
732 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
735 _SEH_EXCEPT(page_fault
)
737 SetLastError(STATUS_ACCESS_VIOLATION
);
744 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
745 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
746 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
752 const CERT_SIGNED_CONTENT_INFO
*info
=
753 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
754 struct AsnEncodeSequenceItem items
[] = {
755 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
756 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
757 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
760 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
761 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
762 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
763 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
766 _SEH_EXCEPT(page_fault
)
768 SetLastError(STATUS_ACCESS_VIOLATION
);
775 /* Like in Windows, this blithely ignores the validity of the passed-in
776 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
777 * decode properly, see CRYPT_AsnDecodeCertInfo.
779 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
780 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
781 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
787 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
788 struct AsnEncodeSequenceItem items
[10] = {
789 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
790 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
791 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
792 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
793 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
794 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
795 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
798 struct AsnConstructedItem constructed
[3] = { { 0 } };
799 DWORD cItem
= 7, cConstructed
= 0;
801 if (info
->IssuerUniqueId
.cbData
)
803 constructed
[cConstructed
].tag
= 1;
804 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
805 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
806 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
807 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
811 if (info
->SubjectUniqueId
.cbData
)
813 constructed
[cConstructed
].tag
= 2;
814 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
815 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
816 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
817 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
821 if (info
->cExtension
)
823 constructed
[cConstructed
].tag
= 3;
824 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
825 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
826 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
827 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
832 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
833 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
835 _SEH_EXCEPT(page_fault
)
837 SetLastError(STATUS_ACCESS_VIOLATION
);
844 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
845 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
847 struct AsnEncodeSequenceItem items
[3] = {
848 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
849 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
855 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
857 if (entry
->cExtension
)
859 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
860 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
864 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
865 pbEncoded
, pcbEncoded
);
867 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
871 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
872 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
873 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
875 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
876 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
877 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
878 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
881 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
885 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
889 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
890 bytesNeeded
= 1 + lenBytes
+ dataLen
;
892 *pcbEncoded
= bytesNeeded
;
895 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
896 pcbEncoded
, bytesNeeded
)))
898 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
899 pbEncoded
= *(BYTE
**)pbEncoded
;
900 *pbEncoded
++ = ASN_SEQUENCEOF
;
901 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
902 pbEncoded
+= lenBytes
;
903 for (i
= 0; i
< cCRLEntry
; i
++)
905 DWORD size
= dataLen
;
907 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
916 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
917 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
918 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
920 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
923 /* CRL_V1 is not encoded */
930 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
931 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
935 /* Like in Windows, this blithely ignores the validity of the passed-in
936 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
937 * decode properly, see CRYPT_AsnDecodeCRLInfo.
939 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
940 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
941 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
947 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
948 struct AsnEncodeSequenceItem items
[7] = {
949 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
950 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
951 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
952 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
957 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
959 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
960 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
965 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
966 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
969 if (info
->cExtension
)
971 items
[cItem
].pvStructInfo
= &info
->cExtension
;
972 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
976 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
977 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
979 _SEH_EXCEPT(page_fault
)
981 SetLastError(STATUS_ACCESS_VIOLATION
);
988 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
992 struct AsnEncodeSequenceItem items
[3] = {
993 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
999 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
1003 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
1004 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1007 items
[cItem
].pvStructInfo
= &ext
->Value
;
1008 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
1011 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
1012 pbEncoded
, pcbEncoded
);
1013 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1017 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
1018 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1019 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1025 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1026 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
1029 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
1033 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
1037 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1038 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1040 *pcbEncoded
= bytesNeeded
;
1043 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1044 pcbEncoded
, bytesNeeded
)))
1046 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1047 pbEncoded
= *(BYTE
**)pbEncoded
;
1048 *pbEncoded
++ = ASN_SEQUENCEOF
;
1049 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1050 pbEncoded
+= lenBytes
;
1051 for (i
= 0; i
< exts
->cExtension
; i
++)
1053 DWORD size
= dataLen
;
1055 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
1063 _SEH_EXCEPT(page_fault
)
1065 SetLastError(STATUS_ACCESS_VIOLATION
);
1072 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
1073 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1074 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1076 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
1077 DWORD bytesNeeded
= 0, lenBytes
;
1082 TRACE("%s\n", debugstr_a(pszObjId
));
1089 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
1091 SetLastError(CRYPT_E_ASN1_ERROR
);
1095 firstByte
= val1
* 40 + val2
;
1096 ptr
= pszObjId
+ firstPos
;
1101 /* note I assume each component is at most 32-bits long in base 2 */
1102 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
1104 if (val1
>= 0x10000000)
1106 else if (val1
>= 0x200000)
1108 else if (val1
>= 0x4000)
1110 else if (val1
>= 0x80)
1120 SetLastError(CRYPT_E_ASN1_ERROR
);
1124 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1128 bytesNeeded
+= 1 + lenBytes
;
1131 if (*pcbEncoded
< bytesNeeded
)
1133 SetLastError(ERROR_MORE_DATA
);
1138 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
1139 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
1140 pbEncoded
+= lenBytes
;
1146 *pbEncoded
++ = firstByte
;
1147 ptr
= pszObjId
+ firstPos
;
1150 sscanf(ptr
, "%d%n", &val
, &pos
);
1152 unsigned char outBytes
[5];
1155 if (val
>= 0x10000000)
1157 else if (val
>= 0x200000)
1159 else if (val
>= 0x4000)
1161 else if (val
>= 0x80)
1165 for (i
= numBytes
; i
> 0; i
--)
1167 outBytes
[i
- 1] = val
& 0x7f;
1170 for (i
= 0; i
< numBytes
- 1; i
++)
1171 *pbEncoded
++ = outBytes
[i
] | 0x80;
1172 *pbEncoded
++ = outBytes
[i
];
1181 *pcbEncoded
= bytesNeeded
;
1185 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
1186 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1189 DWORD bytesNeeded
, lenBytes
, encodedLen
;
1192 switch (value
->dwValueType
)
1194 case CERT_RDN_NUMERIC_STRING
:
1195 tag
= ASN_NUMERICSTRING
;
1196 encodedLen
= value
->Value
.cbData
;
1198 case CERT_RDN_PRINTABLE_STRING
:
1199 tag
= ASN_PRINTABLESTRING
;
1200 encodedLen
= value
->Value
.cbData
;
1202 case CERT_RDN_IA5_STRING
:
1203 tag
= ASN_IA5STRING
;
1204 encodedLen
= value
->Value
.cbData
;
1206 case CERT_RDN_ANY_TYPE
:
1207 /* explicitly disallowed */
1208 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1211 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
1214 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1215 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1218 if (*pcbEncoded
< bytesNeeded
)
1220 SetLastError(ERROR_MORE_DATA
);
1226 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1227 pbEncoded
+= lenBytes
;
1228 switch (value
->dwValueType
)
1230 case CERT_RDN_NUMERIC_STRING
:
1231 case CERT_RDN_PRINTABLE_STRING
:
1232 case CERT_RDN_IA5_STRING
:
1233 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1237 *pcbEncoded
= bytesNeeded
;
1241 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1242 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1244 DWORD bytesNeeded
= 0, lenBytes
, size
;
1247 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1248 0, NULL
, NULL
, &size
);
1251 bytesNeeded
+= size
;
1252 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1253 * with dwValueType, so "cast" it to get its encoded size
1255 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1256 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1259 bytesNeeded
+= size
;
1260 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1261 bytesNeeded
+= 1 + lenBytes
;
1264 if (*pcbEncoded
< bytesNeeded
)
1266 SetLastError(ERROR_MORE_DATA
);
1271 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SEQUENCE
;
1272 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1274 pbEncoded
+= lenBytes
;
1275 size
= bytesNeeded
- 1 - lenBytes
;
1276 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1277 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1281 size
= bytesNeeded
- 1 - lenBytes
- size
;
1282 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1283 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1288 *pcbEncoded
= bytesNeeded
;
1294 static int BLOBComp(const void *l
, const void *r
)
1296 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1299 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1300 ret
= a
->cbData
- b
->cbData
;
1304 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1306 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1307 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1310 CRYPT_DER_BLOB
*blobs
= NULL
;
1314 DWORD bytesNeeded
= 0, lenBytes
, i
;
1320 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1324 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1326 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1328 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1329 NULL
, &blobs
[i
].cbData
);
1331 bytesNeeded
+= blobs
[i
].cbData
;
1335 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1336 bytesNeeded
+= 1 + lenBytes
;
1339 if (*pcbEncoded
< bytesNeeded
)
1341 SetLastError(ERROR_MORE_DATA
);
1346 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1348 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1349 if (!blobs
[i
].pbData
)
1352 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1353 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1358 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1360 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1361 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1363 pbEncoded
+= lenBytes
;
1364 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1366 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1367 pbEncoded
+= blobs
[i
].cbData
;
1372 *pcbEncoded
= bytesNeeded
;
1376 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1377 CryptMemFree(blobs
[i
].pbData
);
1380 _SEH_EXCEPT(page_fault
)
1382 SetLastError(STATUS_ACCESS_VIOLATION
);
1386 CryptMemFree(blobs
);
1390 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1391 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1392 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1398 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1399 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1401 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1403 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1405 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1408 bytesNeeded
+= size
;
1410 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1411 bytesNeeded
+= 1 + lenBytes
;
1415 *pcbEncoded
= bytesNeeded
;
1418 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1419 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1421 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1422 pbEncoded
= *(BYTE
**)pbEncoded
;
1423 *pbEncoded
++ = ASN_SEQUENCEOF
;
1424 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1426 pbEncoded
+= lenBytes
;
1427 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1430 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1431 &info
->rgRDN
[i
], pbEncoded
, &size
);
1435 bytesNeeded
-= size
;
1442 _SEH_EXCEPT(page_fault
)
1444 SetLastError(STATUS_ACCESS_VIOLATION
);
1451 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1452 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1453 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1455 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1464 else if (*pcbEncoded
< 3)
1467 SetLastError(ERROR_MORE_DATA
);
1473 *pbEncoded
++ = ASN_BOOL
;
1475 *pbEncoded
++ = val
? 0xff : 0;
1478 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1482 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1483 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1489 switch (entry
->dwAltNameChoice
)
1491 case CERT_ALT_NAME_RFC822_NAME
:
1492 case CERT_ALT_NAME_DNS_NAME
:
1493 case CERT_ALT_NAME_URL
:
1494 if (entry
->u
.pwszURL
)
1498 /* Not + 1: don't encode the NULL-terminator */
1499 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1500 for (i
= 0; ret
&& i
< dataLen
; i
++)
1502 if (entry
->u
.pwszURL
[i
] > 0x7f)
1504 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1513 case CERT_ALT_NAME_IP_ADDRESS
:
1514 dataLen
= entry
->u
.IPAddress
.cbData
;
1516 case CERT_ALT_NAME_REGISTERED_ID
:
1517 /* FIXME: encode OID */
1518 case CERT_ALT_NAME_OTHER_NAME
:
1519 case CERT_ALT_NAME_DIRECTORY_NAME
:
1520 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1523 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1528 DWORD bytesNeeded
, lenBytes
;
1530 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1531 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1533 *pcbEncoded
= bytesNeeded
;
1534 else if (*pcbEncoded
< bytesNeeded
)
1536 SetLastError(ERROR_MORE_DATA
);
1537 *pcbEncoded
= bytesNeeded
;
1542 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1543 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1544 pbEncoded
+= lenBytes
;
1545 switch (entry
->dwAltNameChoice
)
1547 case CERT_ALT_NAME_RFC822_NAME
:
1548 case CERT_ALT_NAME_DNS_NAME
:
1549 case CERT_ALT_NAME_URL
:
1553 for (i
= 0; i
< dataLen
; i
++)
1554 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1557 case CERT_ALT_NAME_IP_ADDRESS
:
1558 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1562 *pcbEncoded
= bytesNeeded
;
1565 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1569 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1570 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1571 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1577 const CERT_ALT_NAME_INFO
*info
=
1578 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1580 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1583 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1584 * can't encode an erroneous entry index if it's bigger than this.
1586 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1590 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1594 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1596 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1597 * the bad character, now set the index of the bad
1600 *pcbEncoded
= (BYTE
)i
<<
1601 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1606 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1607 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1610 *pcbEncoded
= bytesNeeded
;
1615 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1616 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1618 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1619 pbEncoded
= *(BYTE
**)pbEncoded
;
1620 *pbEncoded
++ = ASN_SEQUENCEOF
;
1621 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1622 pbEncoded
+= lenBytes
;
1623 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1625 DWORD len
= dataLen
;
1627 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1639 _SEH_EXCEPT(page_fault
)
1641 SetLastError(STATUS_ACCESS_VIOLATION
);
1648 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1649 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1650 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1656 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1657 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1658 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1663 items
[cItem
].pvStructInfo
= &info
->fCA
;
1664 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1667 if (info
->fPathLenConstraint
)
1669 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1670 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1673 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1674 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1676 _SEH_EXCEPT(page_fault
)
1678 SetLastError(STATUS_ACCESS_VIOLATION
);
1685 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1686 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1687 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1693 const BLOBHEADER
*hdr
=
1694 (const BLOBHEADER
*)pvStructInfo
;
1696 if (hdr
->bType
!= PUBLICKEYBLOB
)
1698 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1703 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1704 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1705 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1706 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1707 struct AsnEncodeSequenceItem items
[] = {
1708 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1709 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1712 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1713 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1717 _SEH_EXCEPT(page_fault
)
1719 SetLastError(STATUS_ACCESS_VIOLATION
);
1726 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1727 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1728 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1734 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1735 DWORD bytesNeeded
, lenBytes
;
1737 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1738 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1740 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1741 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1744 *pcbEncoded
= bytesNeeded
;
1749 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1750 pcbEncoded
, bytesNeeded
)))
1752 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1753 pbEncoded
= *(BYTE
**)pbEncoded
;
1754 *pbEncoded
++ = ASN_OCTETSTRING
;
1755 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1756 pbEncoded
+= lenBytes
;
1758 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1762 _SEH_EXCEPT(page_fault
)
1764 SetLastError(STATUS_ACCESS_VIOLATION
);
1768 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1772 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1773 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1774 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1780 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1781 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1784 /* yep, MS allows cUnusedBits to be >= 8 */
1785 if (!blob
->cUnusedBits
)
1787 dataBytes
= blob
->cbData
;
1790 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1792 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1793 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1801 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1802 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1805 *pcbEncoded
= bytesNeeded
;
1810 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1811 pcbEncoded
, bytesNeeded
)))
1813 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1814 pbEncoded
= *(BYTE
**)pbEncoded
;
1815 *pbEncoded
++ = ASN_BITSTRING
;
1816 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1817 pbEncoded
+= lenBytes
;
1818 *pbEncoded
++ = unusedBits
;
1821 BYTE mask
= 0xff << unusedBits
;
1825 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1826 pbEncoded
+= dataBytes
- 1;
1828 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1833 _SEH_EXCEPT(page_fault
)
1835 SetLastError(STATUS_ACCESS_VIOLATION
);
1842 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1843 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1844 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1850 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1851 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1856 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
1861 for (i
= 0; i
< newBlob
.cbData
; i
++)
1862 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1868 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1869 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1870 CryptMemFree(newBlob
.pbData
);
1872 _SEH_EXCEPT(page_fault
)
1874 SetLastError(STATUS_ACCESS_VIOLATION
);
1881 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1882 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1883 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1885 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1887 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1888 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1891 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1892 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1893 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1899 DWORD significantBytes
, lenBytes
;
1900 BYTE padByte
= 0, bytesNeeded
;
1902 const CRYPT_INTEGER_BLOB
*blob
=
1903 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1905 significantBytes
= blob
->cbData
;
1906 if (significantBytes
)
1908 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1910 /* negative, lop off leading (little-endian) 0xffs */
1911 for (; significantBytes
> 0 &&
1912 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1914 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1922 /* positive, lop off leading (little-endian) zeroes */
1923 for (; significantBytes
> 0 &&
1924 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1926 if (significantBytes
== 0)
1927 significantBytes
= 1;
1928 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1936 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1938 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1939 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1944 *pcbEncoded
= bytesNeeded
;
1949 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1950 pcbEncoded
, bytesNeeded
)))
1952 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1953 pbEncoded
= *(BYTE
**)pbEncoded
;
1954 *pbEncoded
++ = ASN_INTEGER
;
1957 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1958 pbEncoded
+= lenBytes
;
1959 *pbEncoded
++ = padByte
;
1963 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1964 pbEncoded
+= lenBytes
;
1966 for (; significantBytes
> 0; significantBytes
--)
1967 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1971 _SEH_EXCEPT(page_fault
)
1973 SetLastError(STATUS_ACCESS_VIOLATION
);
1980 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1981 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1982 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1988 DWORD significantBytes
, lenBytes
;
1991 const CRYPT_INTEGER_BLOB
*blob
=
1992 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1994 significantBytes
= blob
->cbData
;
1995 if (significantBytes
)
1997 /* positive, lop off leading (little-endian) zeroes */
1998 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
2001 if (significantBytes
== 0)
2002 significantBytes
= 1;
2003 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
2007 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
2009 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
2010 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
2015 *pcbEncoded
= bytesNeeded
;
2020 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2021 pcbEncoded
, bytesNeeded
)))
2023 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2024 pbEncoded
= *(BYTE
**)pbEncoded
;
2025 *pbEncoded
++ = ASN_INTEGER
;
2028 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
2029 pbEncoded
+= lenBytes
;
2034 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
2035 pbEncoded
+= lenBytes
;
2037 for (; significantBytes
> 0; significantBytes
--)
2038 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
2042 _SEH_EXCEPT(page_fault
)
2044 SetLastError(STATUS_ACCESS_VIOLATION
);
2051 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
2052 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2053 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2055 CRYPT_INTEGER_BLOB blob
;
2058 /* Encode as an unsigned integer, then change the tag to enumerated */
2059 blob
.cbData
= sizeof(DWORD
);
2060 blob
.pbData
= (BYTE
*)pvStructInfo
;
2061 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
2062 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2063 if (ret
&& pbEncoded
)
2065 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2066 pbEncoded
= *(BYTE
**)pbEncoded
;
2067 pbEncoded
[0] = ASN_ENUMERATED
;
2072 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
2073 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2074 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2081 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2082 * temporary buffer because the output buffer is not NULL-terminated.
2085 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2089 *pcbEncoded
= bytesNeeded
;
2094 /* Sanity check the year, this is a two-digit year format */
2095 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2097 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
2099 SetLastError(CRYPT_E_BAD_ENCODE
);
2104 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2105 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2107 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2108 pbEncoded
= *(BYTE
**)pbEncoded
;
2109 buf
[0] = ASN_UTCTIME
;
2110 buf
[1] = bytesNeeded
- 2;
2111 snprintf(buf
+ 2, sizeof(buf
) - 2,
2112 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
2113 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
2114 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2115 sysTime
.wMinute
, sysTime
.wSecond
);
2116 memcpy(pbEncoded
, buf
, bytesNeeded
);
2121 _SEH_EXCEPT(page_fault
)
2123 SetLastError(STATUS_ACCESS_VIOLATION
);
2130 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
2131 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2132 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2139 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2140 * temporary buffer because the output buffer is not NULL-terminated.
2143 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
2147 *pcbEncoded
= bytesNeeded
;
2152 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2155 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2156 pcbEncoded
, bytesNeeded
);
2159 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2160 pbEncoded
= *(BYTE
**)pbEncoded
;
2161 buf
[0] = ASN_GENERALTIME
;
2162 buf
[1] = bytesNeeded
- 2;
2163 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2164 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2165 sysTime
.wMinute
, sysTime
.wSecond
);
2166 memcpy(pbEncoded
, buf
, bytesNeeded
);
2170 _SEH_EXCEPT(page_fault
)
2172 SetLastError(STATUS_ACCESS_VIOLATION
);
2179 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2180 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2181 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2189 /* Check the year, if it's in the UTCTime range call that encode func */
2190 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2192 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2193 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2194 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2196 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2197 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2200 _SEH_EXCEPT(page_fault
)
2202 SetLastError(STATUS_ACCESS_VIOLATION
);
2209 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2210 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2211 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2217 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2218 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2219 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2221 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2222 dataLen
+= seq
->rgValue
[i
].cbData
;
2223 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2224 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2227 *pcbEncoded
= bytesNeeded
;
2232 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2233 pcbEncoded
, bytesNeeded
)))
2235 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2236 pbEncoded
= *(BYTE
**)pbEncoded
;
2237 *pbEncoded
++ = ASN_SEQUENCEOF
;
2238 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2239 pbEncoded
+= lenBytes
;
2240 for (i
= 0; i
< seq
->cValue
; i
++)
2242 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2243 seq
->rgValue
[i
].cbData
);
2244 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2249 _SEH_EXCEPT(page_fault
)
2251 SetLastError(STATUS_ACCESS_VIOLATION
);
2258 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2259 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2260 void *pvEncoded
, DWORD
*pcbEncoded
)
2264 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2266 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2267 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2268 pvEncoded
, pcbEncoded
);
2270 if (!pvEncoded
&& !pcbEncoded
)
2272 SetLastError(ERROR_INVALID_PARAMETER
);
2275 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2276 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2278 SetLastError(ERROR_FILE_NOT_FOUND
);
2282 SetLastError(NOERROR
);
2283 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2284 *(BYTE
**)pvEncoded
= NULL
;
2285 if (!HIWORD(lpszStructType
))
2287 switch (LOWORD(lpszStructType
))
2289 case (WORD
)X509_CERT
:
2290 encodeFunc
= CRYPT_AsnEncodeCert
;
2292 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2293 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2295 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2296 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2298 case (WORD
)X509_EXTENSIONS
:
2299 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2301 case (WORD
)X509_NAME
:
2302 encodeFunc
= CRYPT_AsnEncodeName
;
2304 case (WORD
)X509_PUBLIC_KEY_INFO
:
2305 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2307 case (WORD
)X509_ALTERNATE_NAME
:
2308 encodeFunc
= CRYPT_AsnEncodeAltName
;
2310 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2311 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2313 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2314 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2316 case (WORD
)X509_OCTET_STRING
:
2317 encodeFunc
= CRYPT_AsnEncodeOctets
;
2319 case (WORD
)X509_BITS
:
2320 case (WORD
)X509_KEY_USAGE
:
2321 encodeFunc
= CRYPT_AsnEncodeBits
;
2323 case (WORD
)X509_INTEGER
:
2324 encodeFunc
= CRYPT_AsnEncodeInt
;
2326 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2327 encodeFunc
= CRYPT_AsnEncodeInteger
;
2329 case (WORD
)X509_MULTI_BYTE_UINT
:
2330 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2332 case (WORD
)X509_ENUMERATED
:
2333 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2335 case (WORD
)X509_CHOICE_OF_TIME
:
2336 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2338 case (WORD
)X509_SEQUENCE_OF_ANY
:
2339 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2341 case (WORD
)PKCS_UTC_TIME
:
2342 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2345 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2348 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2349 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2350 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2351 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2352 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2353 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2354 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2355 encodeFunc
= CRYPT_AsnEncodeBits
;
2356 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2357 encodeFunc
= CRYPT_AsnEncodeOctets
;
2358 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2359 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2360 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2361 encodeFunc
= CRYPT_AsnEncodeAltName
;
2362 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2363 encodeFunc
= CRYPT_AsnEncodeAltName
;
2364 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2365 encodeFunc
= CRYPT_AsnEncodeAltName
;
2366 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2367 encodeFunc
= CRYPT_AsnEncodeAltName
;
2368 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2369 encodeFunc
= CRYPT_AsnEncodeAltName
;
2371 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2372 debugstr_a(lpszStructType
));
2374 encodeFunc
= (CryptEncodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2375 lpszStructType
, CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, &lib
);
2377 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2378 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2380 SetLastError(ERROR_FILE_NOT_FOUND
);
2386 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2387 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2388 DWORD
*pcbStructInfo
)
2392 CryptDecodeObjectFunc pCryptDecodeObject
;
2394 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2395 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2396 pvStructInfo
, pcbStructInfo
);
2398 if (!pvStructInfo
&& !pcbStructInfo
)
2400 SetLastError(ERROR_INVALID_PARAMETER
);
2404 /* Try registered DLL first.. */
2405 pCryptDecodeObject
=
2406 (CryptDecodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
2407 lpszStructType
, CRYPT_OID_DECODE_OBJECT_FUNC
, &lib
);
2408 if (pCryptDecodeObject
)
2410 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2411 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2416 /* If not, use CryptDecodeObjectEx */
2417 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2418 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2423 /* Gets the number of length bytes from the given (leading) length byte */
2424 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2426 /* Helper function to get the encoded length of the data starting at pbEncoded,
2427 * where pbEncoded[0] is the tag. If the data are too short to contain a
2428 * length or if the length is too large for cbEncoded, sets an appropriate
2429 * error code and returns FALSE.
2431 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2438 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2441 else if (pbEncoded
[1] <= 0x7f)
2443 if (pbEncoded
[1] + 1 > cbEncoded
)
2445 SetLastError(CRYPT_E_ASN1_EOD
);
2450 *len
= pbEncoded
[1];
2456 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2458 if (lenLen
> sizeof(DWORD
) + 1)
2460 SetLastError(CRYPT_E_ASN1_LARGE
);
2463 else if (lenLen
+ 2 > cbEncoded
)
2465 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2476 out
|= *pbEncoded
++;
2478 if (out
+ lenLen
+ 1 > cbEncoded
)
2480 SetLastError(CRYPT_E_ASN1_EOD
);
2493 /* Helper function to check *pcbStructInfo, set it to the required size, and
2494 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2495 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2496 * pointer to the newly allocated memory.
2498 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2499 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2504 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2506 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2507 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2509 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2510 if (!*(BYTE
**)pvStructInfo
)
2513 *pcbStructInfo
= bytesNeeded
;
2515 else if (*pcbStructInfo
< bytesNeeded
)
2517 *pcbStructInfo
= bytesNeeded
;
2518 SetLastError(ERROR_MORE_DATA
);
2524 /* A few of the members need explanation:
2526 * A sequence is decoded into a struct. The offset member is the
2527 * offset of this item within that struct.
2529 * The decoder function to use. If this is NULL, then the member isn't
2530 * decoded, but minSize space is reserved for it.
2532 * The minimum amount of space occupied after decoding. You must set this.
2534 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2535 * minSize space is filled with 0 for this member. (Any other failure
2536 * results in CRYPT_AsnDecodeSequence failing.)
2537 * hasPointer, pointerOffset, minSize:
2538 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2539 * the offset within the (outer) struct of the data pointer (or to the
2540 * first data pointer, if more than one exist).
2542 * Used by CRYPT_AsnDecodeSequence, not for your use.
2544 struct AsnDecodeSequenceItem
2547 CryptDecodeObjectExFunc decodeFunc
;
2551 DWORD pointerOffset
;
2555 /* This decodes an arbitrary sequence into a contiguous block of memory
2556 * (basically, a struct.) Each element being decoded is described by a struct
2557 * AsnDecodeSequenceItem, see above.
2558 * startingPointer is an optional pointer to the first place where dynamic
2559 * data will be stored. If you know the starting offset, you may pass it
2560 * here. Otherwise, pass NULL, and one will be inferred from the items.
2561 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2562 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2564 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2565 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2566 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2567 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2571 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
2572 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2575 if (pbEncoded
[0] == ASN_SEQUENCE
)
2579 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2581 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2582 DWORD i
, bytesNeeded
= 0, minSize
= 0;
2585 ptr
= pbEncoded
+ 1 + lenBytes
;
2586 for (i
= 0; ret
&& i
< cItem
; i
++)
2590 minSize
+= items
[i
].minSize
;
2591 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2593 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2596 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2598 if (items
[i
].decodeFunc
)
2600 TRACE("sizing item %ld\n", i
);
2601 ret
= items
[i
].decodeFunc(dwCertEncodingType
, NULL
,
2602 ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2603 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2607 /* Account for alignment padding */
2608 bytesNeeded
+= items
[i
].size
;
2609 if (items
[i
].size
% sizeof(DWORD
))
2610 bytesNeeded
+= sizeof(DWORD
) -
2611 items
[i
].size
% sizeof(DWORD
);
2612 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2614 else if (items
[i
].optional
&&
2615 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2617 TRACE("skipping optional item %ld\n", i
);
2618 bytesNeeded
+= items
[i
].minSize
;
2619 SetLastError(NOERROR
);
2623 TRACE("item %ld failed: %08lx\n", i
,
2627 bytesNeeded
+= items
[i
].minSize
;
2630 else if (items
[i
].optional
)
2631 bytesNeeded
+= items
[i
].minSize
;
2634 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2638 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2640 TRACE("%ld remaining bytes, failing\n", cbEncoded
-
2642 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2648 *pcbStructInfo
= bytesNeeded
;
2649 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2650 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2654 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2655 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2656 if (startingPointer
)
2657 nextData
= (BYTE
*)startingPointer
;
2659 nextData
= (BYTE
*)pvStructInfo
+ minSize
;
2660 memset(pvStructInfo
, 0, minSize
);
2661 ptr
= pbEncoded
+ 1 + lenBytes
;
2662 for (i
= 0; ret
&& i
< cItem
; i
++)
2664 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2667 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2669 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2671 if (items
[i
].hasPointer
)
2673 *(BYTE
**)((BYTE
*)pvStructInfo
+
2674 items
[i
].pointerOffset
) = nextData
;
2676 if (items
[i
].decodeFunc
)
2678 TRACE("decoding item %ld\n", i
);
2679 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2680 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2681 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2682 (BYTE
*)pvStructInfo
+ items
[i
].offset
,
2685 TRACE("item %ld failed: %08lx\n", i
,
2689 items
[i
].size
= items
[i
].minSize
;
2692 if (items
[i
].hasPointer
&&
2693 items
[i
].size
> items
[i
].minSize
)
2695 nextData
+= items
[i
].size
-
2697 /* align nextData to DWORD boundaries */
2698 if (items
[i
].size
% sizeof(DWORD
))
2700 nextData
+= sizeof(DWORD
) -
2701 items
[i
].size
% sizeof(DWORD
);
2704 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2706 else if (items
[i
].optional
&&
2707 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2709 SetLastError(NOERROR
);
2713 else if (!items
[i
].optional
)
2715 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2725 SetLastError(CRYPT_E_ASN1_BADTAG
);
2728 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2732 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2733 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2734 * to CRYPT_E_ASN1_CORRUPT.
2735 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2738 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2739 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2740 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2745 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2747 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2748 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2750 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2751 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2754 *pcbStructInfo
= bytesNeeded
;
2755 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2756 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2758 CRYPT_DER_BLOB
*blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
2760 blob
->cbData
= 1 + lenBytes
+ dataLen
;
2763 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2764 blob
->pbData
= (BYTE
*)pbEncoded
;
2767 assert(blob
->pbData
);
2768 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
2773 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2781 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2782 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
2783 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2784 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2788 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
2789 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2791 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2794 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
2795 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
2796 pvStructInfo
, pcbStructInfo
);
2797 if (ret
&& pvStructInfo
)
2799 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2806 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2808 temp
= blob
->pbData
[i
];
2809 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2810 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2814 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2818 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
2819 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2820 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2824 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2825 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2829 struct AsnDecodeSequenceItem items
[] = {
2830 { offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
2831 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2832 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
2833 { offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
),
2834 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2835 FALSE
, TRUE
, offsetof(CERT_SIGNED_CONTENT_INFO
,
2836 SignatureAlgorithm
.pszObjId
), 0 },
2837 { offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
2838 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2839 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
2842 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
2843 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
2844 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2845 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2846 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2848 _SEH_EXCEPT(page_fault
)
2850 SetLastError(STATUS_ACCESS_VIOLATION
);
2857 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
2858 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2859 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2863 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
))
2867 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2869 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2871 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2872 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
2873 pvStructInfo
, pcbStructInfo
);
2878 SetLastError(CRYPT_E_ASN1_BADTAG
);
2884 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
2885 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2886 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2890 struct AsnDecodeSequenceItem items
[] = {
2891 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
2892 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2893 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
2894 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2897 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2898 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2899 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2903 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
2904 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2905 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2909 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3))
2913 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2915 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2917 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
2918 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
2919 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2924 SetLastError(CRYPT_E_ASN1_BADTAG
);
2930 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
2931 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2932 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2936 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2937 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2941 struct AsnDecodeSequenceItem items
[] = {
2942 { offsetof(CERT_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
2943 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
2944 { offsetof(CERT_INFO
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2945 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2946 SerialNumber
.pbData
), 0 },
2947 { offsetof(CERT_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
2948 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2949 SignatureAlgorithm
.pszObjId
), 0 },
2950 { offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
2951 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2953 { offsetof(CERT_INFO
, NotBefore
), CRYPT_AsnDecodeValidity
,
2954 sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
, FALSE
, 0 },
2955 { offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
2956 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2958 { offsetof(CERT_INFO
, SubjectPublicKeyInfo
), CRYPT_AsnDecodePubKeyInfo
,
2959 sizeof(CERT_PUBLIC_KEY_INFO
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2960 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
2961 { offsetof(CERT_INFO
, IssuerUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2962 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2963 IssuerUniqueId
.pbData
), 0 },
2964 { offsetof(CERT_INFO
, SubjectUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2965 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2966 SubjectUniqueId
.pbData
), 0 },
2967 { offsetof(CERT_INFO
, cExtension
), CRYPT_AsnDecodeCertExtensions
,
2968 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2972 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2973 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2974 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2976 _SEH_EXCEPT(page_fault
)
2978 SetLastError(STATUS_ACCESS_VIOLATION
);
2985 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2986 DWORD dwFlags
, PCRL_ENTRY entry
, DWORD
*pcbEntry
)
2989 struct AsnDecodeSequenceItem items
[] = {
2990 { offsetof(CRL_ENTRY
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2991 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CRL_ENTRY
,
2992 SerialNumber
.pbData
), 0 },
2993 { offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
2994 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2995 { offsetof(CRL_ENTRY
, cExtension
), CRYPT_AsnDecodeExtensionsInternal
,
2996 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CRL_ENTRY
,
3000 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
3003 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3004 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3005 NULL
, entry
, pcbEntry
, entry
? entry
->SerialNumber
.pbData
: NULL
);
3006 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3010 typedef struct _WINE_CRL_ENTRIES
{
3012 PCRL_ENTRY rgCRLEntry
;
3013 } WINE_CRL_ENTRIES
, *PWINE_CRL_ENTRIES
;
3015 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
3016 * been set prior to calling.
3018 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
3019 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3020 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3024 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3025 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3027 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3029 DWORD dataLen
, bytesNeeded
;
3031 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3033 DWORD cCRLEntry
= 0;
3034 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3036 bytesNeeded
= sizeof(WINE_CRL_ENTRIES
);
3042 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3043 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3046 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3047 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3053 bytesNeeded
+= size
;
3054 ret
= CRYPT_GetLen(ptr
,
3055 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3057 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3064 *pcbStructInfo
= bytesNeeded
;
3065 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3066 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3071 PWINE_CRL_ENTRIES entries
;
3073 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3074 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3075 *pcbStructInfo
= bytesNeeded
;
3076 entries
= (PWINE_CRL_ENTRIES
)pvStructInfo
;
3077 entries
->cCRLEntry
= cCRLEntry
;
3078 assert(entries
->rgCRLEntry
);
3079 nextData
= (BYTE
*)entries
->rgCRLEntry
+
3080 entries
->cCRLEntry
* sizeof(CRL_ENTRY
);
3081 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3082 i
< cCRLEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
3085 entries
->rgCRLEntry
[i
].SerialNumber
.pbData
= nextData
;
3087 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
3088 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3089 &entries
->rgCRLEntry
[i
], &size
);
3094 bytesNeeded
-= size
;
3095 /* Increment nextData by the difference of the
3096 * minimum size and the actual size.
3098 if (size
> sizeof(CRL_ENTRY
))
3099 nextData
+= size
- sizeof(CRL_ENTRY
);
3100 ret
= CRYPT_GetLen(ptr
,
3101 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3103 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3112 SetLastError(CRYPT_E_ASN1_BADTAG
);
3115 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3119 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
3120 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3121 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3125 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3126 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3130 struct AsnDecodeSequenceItem items
[] = {
3131 { offsetof(CRL_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
3132 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3133 { offsetof(CRL_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
3134 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3135 SignatureAlgorithm
.pszObjId
), 0 },
3136 { offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3137 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3139 { offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3140 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3141 { offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3142 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
3143 { offsetof(CRL_INFO
, cCRLEntry
), CRYPT_AsnDecodeCRLEntries
,
3144 sizeof(WINE_CRL_ENTRIES
), TRUE
, TRUE
, offsetof(CRL_INFO
,
3146 /* Note that the extensions are ignored by MS, so I'll ignore them too
3148 { offsetof(CRL_INFO
, cExtension
), NULL
,
3149 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
3152 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3153 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3154 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3156 _SEH_EXCEPT(page_fault
)
3158 SetLastError(STATUS_ACCESS_VIOLATION
);
3163 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3167 /* Differences between this and CRYPT_AsnDecodeOid:
3168 * - pvStructInfo is a LPSTR *, not an LPSTR
3169 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3170 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3173 static BOOL WINAPI
CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType
,
3174 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3175 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3179 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3180 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3182 ret
= CRYPT_AsnDecodeOid(pbEncoded
, cbEncoded
, dwFlags
,
3183 pvStructInfo
? *(LPSTR
*)pvStructInfo
: NULL
, pcbStructInfo
);
3184 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
3185 *pcbStructInfo
+= sizeof(LPSTR
);
3186 if (ret
&& pvStructInfo
)
3187 TRACE("returning %s\n", debugstr_a(*(LPSTR
*)pvStructInfo
));
3191 /* Warning: assumes ext->pszObjId is set ahead of time! */
3192 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3193 DWORD dwFlags
, CERT_EXTENSION
*ext
, DWORD
*pcbExt
)
3195 struct AsnDecodeSequenceItem items
[] = {
3196 { offsetof(CERT_EXTENSION
, pszObjId
), CRYPT_AsnDecodeOidWrapper
,
3197 sizeof(LPSTR
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
, pszObjId
), 0 },
3198 { offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
3199 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
3200 { offsetof(CERT_EXTENSION
, Value
), CRYPT_AsnDecodeOctetsInternal
,
3201 sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
,
3206 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
3210 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
3211 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3212 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3213 ext
, pcbExt
, ext
? ext
->pszObjId
: NULL
);
3215 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
3216 debugstr_a(ext
->pszObjId
));
3217 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3221 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
3222 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3223 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3227 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3228 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3230 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3232 DWORD dataLen
, bytesNeeded
;
3234 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3236 DWORD cExtension
= 0;
3237 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3239 bytesNeeded
= sizeof(CERT_EXTENSIONS
);
3245 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3246 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3249 ret
= CRYPT_AsnDecodeExtension(ptr
,
3250 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3256 bytesNeeded
+= size
;
3257 ret
= CRYPT_GetLen(ptr
,
3258 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3260 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3267 *pcbStructInfo
= bytesNeeded
;
3268 else if (*pcbStructInfo
< bytesNeeded
)
3270 SetLastError(ERROR_MORE_DATA
);
3271 *pcbStructInfo
= bytesNeeded
;
3279 CERT_EXTENSIONS
*exts
;
3281 *pcbStructInfo
= bytesNeeded
;
3282 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3283 exts
->cExtension
= cExtension
;
3284 assert(exts
->rgExtension
);
3285 nextData
= (BYTE
*)exts
->rgExtension
+
3286 exts
->cExtension
* sizeof(CERT_EXTENSION
);
3287 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3288 i
< cExtension
&& ptr
- pbEncoded
- 1 - lenBytes
<
3291 exts
->rgExtension
[i
].pszObjId
= (LPSTR
)nextData
;
3293 ret
= CRYPT_AsnDecodeExtension(ptr
,
3294 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3295 &exts
->rgExtension
[i
], &size
);
3300 bytesNeeded
-= size
;
3301 if (size
> sizeof(CERT_EXTENSION
))
3302 nextData
+= size
- sizeof(CERT_EXTENSION
);
3303 ret
= CRYPT_GetLen(ptr
,
3304 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3306 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3315 SetLastError(CRYPT_E_ASN1_BADTAG
);
3321 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3322 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3323 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3329 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3330 lpszStructType
, pbEncoded
, cbEncoded
,
3331 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3332 if (ret
&& pvStructInfo
)
3334 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3335 pcbStructInfo
, *pcbStructInfo
);
3338 CERT_EXTENSIONS
*exts
;
3340 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3341 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3342 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3343 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3344 sizeof(CERT_EXTENSIONS
));
3345 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3346 lpszStructType
, pbEncoded
, cbEncoded
,
3347 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3352 _SEH_EXCEPT(page_fault
)
3354 SetLastError(STATUS_ACCESS_VIOLATION
);
3361 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3362 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3363 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
)
3367 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, pszObjId
,
3372 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3376 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3378 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3383 /* The largest possible string for the first two components
3384 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3389 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3390 pbEncoded
[1 + lenBytes
] / 40,
3391 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3393 bytesNeeded
= strlen(firstTwo
) + 1;
3394 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3395 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3397 /* large enough for ".4000000" */
3401 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3408 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3411 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3418 snprintf(str
, sizeof(str
), ".%d", val
);
3419 bytesNeeded
+= strlen(str
);
3423 *pcbObjId
= bytesNeeded
;
3424 else if (*pcbObjId
< bytesNeeded
)
3426 *pcbObjId
= bytesNeeded
;
3427 SetLastError(ERROR_MORE_DATA
);
3433 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3434 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3436 pszObjId
+= strlen(pszObjId
);
3437 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3438 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3442 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3451 sprintf(pszObjId
, ".%d", val
);
3452 pszObjId
+= strlen(pszObjId
);
3458 *pcbObjId
= bytesNeeded
;
3463 SetLastError(CRYPT_E_ASN1_BADTAG
);
3467 _SEH_EXCEPT(page_fault
)
3469 SetLastError(STATUS_ACCESS_VIOLATION
);
3476 /* Warning: this assumes the address of value->Value.pbData is already set, in
3477 * order to avoid overwriting memory. (In some cases, it may change it, if it
3478 * doesn't copy anything to memory.) Be sure to set it correctly!
3480 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(const BYTE
*pbEncoded
,
3481 DWORD cbEncoded
, DWORD dwFlags
, CERT_NAME_VALUE
*value
, DWORD
*pcbValue
)
3489 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3491 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3493 switch (pbEncoded
[0])
3495 case ASN_NUMERICSTRING
:
3496 case ASN_PRINTABLESTRING
:
3500 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3501 SetLastError(OSS_UNIMPLEMENTED
);
3506 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3508 switch (pbEncoded
[0])
3510 case ASN_NUMERICSTRING
:
3511 case ASN_PRINTABLESTRING
:
3513 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3514 bytesNeeded
+= dataLen
;
3518 *pcbValue
= bytesNeeded
;
3519 else if (*pcbValue
< bytesNeeded
)
3521 *pcbValue
= bytesNeeded
;
3522 SetLastError(ERROR_MORE_DATA
);
3527 *pcbValue
= bytesNeeded
;
3528 switch (pbEncoded
[0])
3530 case ASN_NUMERICSTRING
:
3531 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3533 case ASN_PRINTABLESTRING
:
3534 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3537 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3542 switch (pbEncoded
[0])
3544 case ASN_NUMERICSTRING
:
3545 case ASN_PRINTABLESTRING
:
3547 value
->Value
.cbData
= dataLen
;
3548 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3549 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3553 assert(value
->Value
.pbData
);
3554 memcpy(value
->Value
.pbData
,
3555 pbEncoded
+ 1 + lenBytes
, dataLen
);
3562 value
->Value
.cbData
= 0;
3563 value
->Value
.pbData
= NULL
;
3569 _SEH_EXCEPT(page_fault
)
3571 SetLastError(STATUS_ACCESS_VIOLATION
);
3578 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3579 * at the moment because of the ASN_CONSTRUCTOR tag.)
3581 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
,
3582 DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN_ATTR
*attr
, DWORD
*pcbAttr
)
3588 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
3590 DWORD bytesNeeded
, dataLen
, size
;
3593 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3595 /* The data length must be at least 4, two for the tag and
3596 * length for the OID, and two for the string (assuming both
3597 * have short-form lengths.)
3601 SetLastError(CRYPT_E_ASN1_EOD
);
3606 bytesNeeded
= sizeof(CERT_RDN_ATTR
);
3607 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3608 ret
= CRYPT_AsnDecodeOid(pbEncoded
+ 1 + lenBytes
,
3609 cbEncoded
- 1 - lenBytes
, dwFlags
, NULL
, &size
);
3612 /* ugly: need to know the size of the next element of
3613 * the sequence, so get it directly
3615 DWORD objIdOfset
= 1 + lenBytes
, objIdLen
,
3616 nameValueOffset
= 0;
3618 ret
= CRYPT_GetLen(pbEncoded
+ objIdOfset
,
3619 cbEncoded
- objIdOfset
, &objIdLen
);
3620 bytesNeeded
+= size
;
3621 /* hack: like encoding, this takes advantage of the
3622 * fact that the rest of the structure is identical to
3623 * a CERT_NAME_VALUE.
3627 nameValueOffset
= objIdOfset
+ objIdLen
+ 1 +
3628 GET_LEN_BYTES(pbEncoded
[objIdOfset
]);
3629 ret
= CRYPT_AsnDecodeNameValue(
3630 pbEncoded
+ nameValueOffset
,
3631 cbEncoded
- nameValueOffset
, dwFlags
, NULL
, &size
);
3635 bytesNeeded
+= size
;
3637 *pcbAttr
= bytesNeeded
;
3638 else if (*pcbAttr
< bytesNeeded
)
3640 *pcbAttr
= bytesNeeded
;
3641 SetLastError(ERROR_MORE_DATA
);
3646 BYTE
*originalData
= attr
->Value
.pbData
;
3648 *pcbAttr
= bytesNeeded
;
3649 /* strange: decode the value first, because it
3650 * has a counted size, and we can store the OID
3651 * after it. Keep track of the original data
3652 * pointer, we'll need to know whether it was
3656 ret
= CRYPT_AsnDecodeNameValue(
3657 pbEncoded
+ nameValueOffset
,
3658 cbEncoded
- nameValueOffset
, dwFlags
,
3659 (CERT_NAME_VALUE
*)&attr
->dwValueType
, &size
);
3664 /* if the data were copied to the
3665 * original location, the OID goes
3666 * after. Otherwise it goes in the
3667 * spot originally reserved for the
3670 if (attr
->Value
.pbData
== originalData
)
3672 (LPSTR
)(attr
->Value
.pbData
+
3673 attr
->Value
.cbData
);
3676 (LPSTR
)originalData
;
3677 size
= bytesNeeded
- size
;
3678 ret
= CRYPT_AsnDecodeOid(
3679 pbEncoded
+ objIdOfset
,
3680 cbEncoded
- objIdOfset
,
3681 dwFlags
, attr
->pszObjId
, &size
);
3684 attr
->pszObjId
= NULL
;
3694 SetLastError(CRYPT_E_ASN1_BADTAG
);
3698 _SEH_EXCEPT(page_fault
)
3700 SetLastError(STATUS_ACCESS_VIOLATION
);
3707 static BOOL WINAPI
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3708 DWORD dwFlags
, CERT_RDN
*rdn
, DWORD
*pcbRdn
)
3714 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SETOF
))
3718 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3720 DWORD bytesNeeded
, cRDNAttr
= 0;
3721 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3723 bytesNeeded
= sizeof(CERT_RDN
);
3729 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3730 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3732 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3733 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3739 bytesNeeded
+= size
;
3740 ret
= CRYPT_GetLen(ptr
,
3741 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3743 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3750 *pcbRdn
= bytesNeeded
;
3751 else if (*pcbRdn
< bytesNeeded
)
3753 *pcbRdn
= bytesNeeded
;
3754 SetLastError(ERROR_MORE_DATA
);
3763 *pcbRdn
= bytesNeeded
;
3764 rdn
->cRDNAttr
= cRDNAttr
;
3765 rdn
->rgRDNAttr
= (CERT_RDN_ATTR
*)((BYTE
*)rdn
+
3767 nextData
= (BYTE
*)rdn
->rgRDNAttr
+
3768 rdn
->cRDNAttr
* sizeof(CERT_RDN_ATTR
);
3769 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3770 i
< cRDNAttr
&& ptr
- pbEncoded
- 1 - lenBytes
<
3773 rdn
->rgRDNAttr
[i
].Value
.pbData
= nextData
;
3775 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3776 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3777 &rdn
->rgRDNAttr
[i
], &size
);
3782 bytesNeeded
-= size
;
3783 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3784 * data may not have been copied.
3786 if (rdn
->rgRDNAttr
[i
].Value
.pbData
== nextData
)
3788 rdn
->rgRDNAttr
[i
].Value
.cbData
;
3789 /* Ugly: the OID, if copied, is stored in
3790 * memory after the value, so increment by its
3791 * string length if it's set and points here.
3793 if ((const BYTE
*)rdn
->rgRDNAttr
[i
].pszObjId
3796 rdn
->rgRDNAttr
[i
].pszObjId
) + 1;
3797 ret
= CRYPT_GetLen(ptr
,
3798 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3800 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3809 SetLastError(CRYPT_E_ASN1_BADTAG
);
3813 _SEH_EXCEPT(page_fault
)
3815 SetLastError(STATUS_ACCESS_VIOLATION
);
3822 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3823 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3824 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3830 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCEOF
))
3834 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3836 DWORD bytesNeeded
, cRDN
= 0;
3837 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3839 bytesNeeded
= sizeof(CERT_NAME_INFO
);
3844 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3845 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3849 ret
= CRYPT_AsnDecodeRdn(ptr
,
3850 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3856 bytesNeeded
+= size
;
3857 ret
= CRYPT_GetLen(ptr
,
3858 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3860 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3867 *pcbStructInfo
= bytesNeeded
;
3868 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3869 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3871 CERT_NAME_INFO
*info
;
3873 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3874 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3875 info
= (CERT_NAME_INFO
*)pvStructInfo
;
3877 if (info
->cRDN
== 0)
3885 info
->rgRDN
= (CERT_RDN
*)((BYTE
*)pvStructInfo
+
3886 sizeof(CERT_NAME_INFO
));
3887 nextData
= (BYTE
*)info
->rgRDN
+
3888 info
->cRDN
* sizeof(CERT_RDN
);
3889 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3890 i
< cRDN
&& ptr
- pbEncoded
- 1 - lenBytes
<
3893 info
->rgRDN
[i
].rgRDNAttr
=
3894 (CERT_RDN_ATTR
*)nextData
;
3896 ret
= CRYPT_AsnDecodeRdn(ptr
,
3897 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3898 &info
->rgRDN
[i
], &size
);
3904 bytesNeeded
-= size
;
3905 ret
= CRYPT_GetLen(ptr
,
3906 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3908 ptr
+= nextLen
+ 1 +
3909 GET_LEN_BYTES(ptr
[1]);
3919 SetLastError(CRYPT_E_ASN1_BADTAG
);
3923 _SEH_EXCEPT(page_fault
)
3925 SetLastError(STATUS_ACCESS_VIOLATION
);
3932 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
3933 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3934 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3937 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
3939 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3940 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3942 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3943 bytesNeeded
+= cbEncoded
;
3945 *pcbStructInfo
= bytesNeeded
;
3946 else if (*pcbStructInfo
< bytesNeeded
)
3948 SetLastError(ERROR_MORE_DATA
);
3949 *pcbStructInfo
= bytesNeeded
;
3954 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
3956 *pcbStructInfo
= bytesNeeded
;
3957 blob
->cbData
= cbEncoded
;
3958 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3959 blob
->pbData
= (LPBYTE
)pbEncoded
;
3962 assert(blob
->pbData
);
3963 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3969 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3970 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3971 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3973 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3974 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3976 struct AsnDecodeSequenceItem items
[] = {
3977 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
3978 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3979 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
3980 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
3981 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
3982 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
3985 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3986 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3988 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3989 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3990 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
3991 if (ret
&& pvStructInfo
)
3993 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
3994 debugstr_a(algo
->pszObjId
));
3999 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
4000 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4001 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4007 struct AsnDecodeSequenceItem items
[] = {
4008 { offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
4009 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
4010 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
4011 Algorithm
.pszObjId
) },
4012 { offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
4013 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
4014 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
4017 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4018 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4019 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4021 _SEH_EXCEPT(page_fault
)
4023 SetLastError(STATUS_ACCESS_VIOLATION
);
4030 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
4031 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4032 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4038 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4041 if (pbEncoded
[0] != ASN_BOOL
)
4043 SetLastError(CRYPT_E_ASN1_BADTAG
);
4046 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
4048 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4051 if (pbEncoded
[1] > 1)
4053 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4058 *pcbStructInfo
= sizeof(BOOL
);
4061 else if (*pcbStructInfo
< sizeof(BOOL
))
4063 *pcbStructInfo
= sizeof(BOOL
);
4064 SetLastError(ERROR_MORE_DATA
);
4069 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
4072 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4076 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4077 DWORD dwFlags
, CERT_ALT_NAME_ENTRY
*entry
, DWORD
*pcbEntry
)
4079 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
4084 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4087 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
4089 SetLastError(CRYPT_E_ASN1_BADTAG
);
4092 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4093 if (1 + lenBytes
> cbEncoded
)
4095 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4098 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4100 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4102 case 1: /* rfc822Name */
4103 case 2: /* dNSName */
4104 case 6: /* uniformResourceIdentifier */
4105 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
4107 case 7: /* iPAddress */
4108 bytesNeeded
+= dataLen
;
4110 case 8: /* registeredID */
4111 /* FIXME: decode as OID */
4112 case 0: /* otherName */
4113 case 4: /* directoryName */
4115 SetLastError(CRYPT_E_ASN1_BADTAG
);
4118 case 3: /* x400Address, unimplemented */
4119 case 5: /* ediPartyName, unimplemented */
4120 SetLastError(CRYPT_E_ASN1_BADTAG
);
4124 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4130 *pcbEntry
= bytesNeeded
;
4131 else if (*pcbEntry
< bytesNeeded
)
4133 SetLastError(ERROR_MORE_DATA
);
4138 /* MS used values one greater than the asn1 ones.. sigh */
4139 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
4140 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
4142 case 1: /* rfc822Name */
4143 case 2: /* dNSName */
4144 case 6: /* uniformResourceIdentifier */
4148 for (i
= 0; i
< dataLen
; i
++)
4149 entry
->u
.pwszURL
[i
] =
4150 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
4151 entry
->u
.pwszURL
[i
] = 0;
4154 case 7: /* iPAddress */
4155 /* The next data pointer is in the pwszURL spot, that is,
4156 * the first 4 bytes. Need to move it to the next spot.
4158 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
4159 entry
->u
.IPAddress
.cbData
= dataLen
;
4160 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
4170 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
4171 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4172 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4178 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
4182 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4184 DWORD bytesNeeded
, cEntry
= 0;
4185 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4187 bytesNeeded
= sizeof(CERT_ALT_NAME_INFO
);
4192 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4193 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
4197 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4198 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
4204 bytesNeeded
+= size
;
4205 ret
= CRYPT_GetLen(ptr
,
4206 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4208 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
4215 *pcbStructInfo
= bytesNeeded
;
4216 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4217 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4219 CERT_ALT_NAME_INFO
*info
;
4221 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4222 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4223 info
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
4224 info
->cAltEntry
= 0;
4226 info
->rgAltEntry
= NULL
;
4234 (CERT_ALT_NAME_ENTRY
*)((BYTE
*)pvStructInfo
+
4235 sizeof(CERT_ALT_NAME_INFO
));
4236 nextData
= (BYTE
*)info
->rgAltEntry
+
4237 cEntry
* sizeof(CERT_ALT_NAME_ENTRY
);
4238 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4239 i
< cEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
4242 info
->rgAltEntry
[i
].u
.pwszURL
=
4245 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4246 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
4247 &info
->rgAltEntry
[i
], &size
);
4254 sizeof(CERT_ALT_NAME_ENTRY
);
4255 bytesNeeded
-= size
;
4256 ret
= CRYPT_GetLen(ptr
,
4257 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4259 ptr
+= nextLen
+ 1 +
4260 GET_LEN_BYTES(ptr
[1]);
4270 SetLastError(CRYPT_E_ASN1_BADTAG
);
4274 _SEH_EXCEPT(page_fault
)
4276 SetLastError(STATUS_ACCESS_VIOLATION
);
4283 struct PATH_LEN_CONSTRAINT
4285 BOOL fPathLenConstraint
;
4286 DWORD dwPathLenConstraint
;
4289 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
4290 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4291 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4297 if (pbEncoded
[0] == ASN_INTEGER
)
4299 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
4302 *pcbStructInfo
= bytesNeeded
;
4303 else if (*pcbStructInfo
< bytesNeeded
)
4305 SetLastError(ERROR_MORE_DATA
);
4306 *pcbStructInfo
= bytesNeeded
;
4311 struct PATH_LEN_CONSTRAINT
*constraint
=
4312 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
4313 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
4315 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
4316 pbEncoded
, cbEncoded
, 0, NULL
,
4317 &constraint
->dwPathLenConstraint
, &size
);
4319 constraint
->fPathLenConstraint
= TRUE
;
4320 TRACE("got an int, dwPathLenConstraint is %ld\n",
4321 constraint
->dwPathLenConstraint
);
4326 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4330 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4334 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
4335 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4336 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4342 struct AsnDecodeSequenceItem items
[] = {
4343 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
), CRYPT_AsnDecodeBool
,
4344 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
4345 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fPathLenConstraint
),
4346 CRYPT_AsnDecodePathLenConstraint
, sizeof(struct PATH_LEN_CONSTRAINT
),
4347 TRUE
, FALSE
, 0, 0 },
4350 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4351 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4352 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4354 _SEH_EXCEPT(page_fault
)
4356 SetLastError(STATUS_ACCESS_VIOLATION
);
4363 #define RSA1_MAGIC 0x31415352
4365 struct DECODED_RSA_PUB_KEY
4368 CRYPT_INTEGER_BLOB modulus
;
4371 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4372 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4373 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4379 struct AsnDecodeSequenceItem items
[] = {
4380 { offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4381 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4382 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4384 { offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4385 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4387 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4390 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4391 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4392 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4395 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4396 decodedKey
->modulus
.cbData
;
4400 *pcbStructInfo
= bytesNeeded
;
4403 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4404 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4407 RSAPUBKEY
*rsaPubKey
;
4409 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4410 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4411 hdr
= (BLOBHEADER
*)pvStructInfo
;
4412 hdr
->bType
= PUBLICKEYBLOB
;
4413 hdr
->bVersion
= CUR_BLOB_VERSION
;
4415 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4416 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4417 sizeof(BLOBHEADER
));
4418 rsaPubKey
->magic
= RSA1_MAGIC
;
4419 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4420 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4421 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4422 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4423 decodedKey
->modulus
.cbData
);
4425 LocalFree(decodedKey
);
4428 _SEH_EXCEPT(page_fault
)
4430 SetLastError(STATUS_ACCESS_VIOLATION
);
4437 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
4438 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4439 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4443 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4444 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4446 if (pbEncoded
[0] == ASN_OCTETSTRING
)
4448 DWORD bytesNeeded
, dataLen
;
4450 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4452 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4453 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4455 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4457 *pcbStructInfo
= bytesNeeded
;
4458 else if (*pcbStructInfo
< bytesNeeded
)
4460 SetLastError(ERROR_MORE_DATA
);
4461 *pcbStructInfo
= bytesNeeded
;
4466 CRYPT_DATA_BLOB
*blob
;
4467 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4469 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4470 blob
->cbData
= dataLen
;
4471 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4472 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4475 assert(blob
->pbData
);
4477 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4485 SetLastError(CRYPT_E_ASN1_BADTAG
);
4491 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4492 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4493 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4497 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4498 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4504 if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4505 lpszStructType
, pbEncoded
, cbEncoded
,
4506 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4509 *pcbStructInfo
= bytesNeeded
;
4510 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4511 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4513 CRYPT_DATA_BLOB
*blob
;
4515 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4516 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4517 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4518 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
4519 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4520 lpszStructType
, pbEncoded
, cbEncoded
,
4521 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4527 SetLastError(CRYPT_E_ASN1_BADTAG
);
4531 _SEH_EXCEPT(page_fault
)
4533 SetLastError(STATUS_ACCESS_VIOLATION
);
4540 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4541 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4542 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4546 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4547 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4549 if (pbEncoded
[0] == ASN_BITSTRING
)
4551 DWORD bytesNeeded
, dataLen
;
4553 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4555 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4556 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4558 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4560 *pcbStructInfo
= bytesNeeded
;
4561 else if (*pcbStructInfo
< bytesNeeded
)
4563 *pcbStructInfo
= bytesNeeded
;
4564 SetLastError(ERROR_MORE_DATA
);
4569 CRYPT_BIT_BLOB
*blob
;
4571 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4572 blob
->cbData
= dataLen
- 1;
4573 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4574 GET_LEN_BYTES(pbEncoded
[1]));
4575 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4577 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4578 GET_LEN_BYTES(pbEncoded
[1]);
4582 assert(blob
->pbData
);
4585 BYTE mask
= 0xff << blob
->cUnusedBits
;
4587 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4588 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4589 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4597 SetLastError(CRYPT_E_ASN1_BADTAG
);
4600 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4604 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4605 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4606 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4610 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4611 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4617 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4618 lpszStructType
, pbEncoded
, cbEncoded
,
4619 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4622 *pcbStructInfo
= bytesNeeded
;
4623 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4624 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4626 CRYPT_BIT_BLOB
*blob
;
4628 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4629 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4630 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4631 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4632 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4633 lpszStructType
, pbEncoded
, cbEncoded
,
4634 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4639 _SEH_EXCEPT(page_fault
)
4641 SetLastError(STATUS_ACCESS_VIOLATION
);
4645 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4649 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4650 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4651 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4657 *pcbStructInfo
= sizeof(int);
4662 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4663 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4664 DWORD size
= sizeof(buf
);
4666 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4667 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4668 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4671 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4672 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4676 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4677 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4678 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4680 /* initialize to a negative value to sign-extend */
4685 for (i
= 0; i
< blob
->cbData
; i
++)
4688 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4690 memcpy(pvStructInfo
, &val
, sizeof(int));
4693 else if (GetLastError() == ERROR_MORE_DATA
)
4694 SetLastError(CRYPT_E_ASN1_LARGE
);
4696 _SEH_EXCEPT(page_fault
)
4698 SetLastError(STATUS_ACCESS_VIOLATION
);
4705 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4706 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4707 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4711 if (pbEncoded
[0] == ASN_INTEGER
)
4713 DWORD bytesNeeded
, dataLen
;
4715 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4717 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4719 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4721 *pcbStructInfo
= bytesNeeded
;
4722 else if (*pcbStructInfo
< bytesNeeded
)
4724 *pcbStructInfo
= bytesNeeded
;
4725 SetLastError(ERROR_MORE_DATA
);
4730 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4732 blob
->cbData
= dataLen
;
4733 assert(blob
->pbData
);
4738 for (i
= 0; i
< blob
->cbData
; i
++)
4740 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4749 SetLastError(CRYPT_E_ASN1_BADTAG
);
4755 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4756 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4757 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4765 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4766 lpszStructType
, pbEncoded
, cbEncoded
,
4767 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4770 *pcbStructInfo
= bytesNeeded
;
4771 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4772 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4774 CRYPT_INTEGER_BLOB
*blob
;
4776 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4777 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4778 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4779 blob
->pbData
= (BYTE
*)pvStructInfo
+
4780 sizeof(CRYPT_INTEGER_BLOB
);
4781 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4782 lpszStructType
, pbEncoded
, cbEncoded
,
4783 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4788 _SEH_EXCEPT(page_fault
)
4790 SetLastError(STATUS_ACCESS_VIOLATION
);
4797 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
4798 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
4799 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4800 void *pvStructInfo
, DWORD
*pcbStructInfo
)
4804 if (pbEncoded
[0] == ASN_INTEGER
)
4806 DWORD bytesNeeded
, dataLen
;
4808 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4810 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4812 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4814 *pcbStructInfo
= bytesNeeded
;
4815 else if (*pcbStructInfo
< bytesNeeded
)
4817 *pcbStructInfo
= bytesNeeded
;
4818 SetLastError(ERROR_MORE_DATA
);
4823 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4825 blob
->cbData
= dataLen
;
4826 assert(blob
->pbData
);
4827 /* remove leading zero byte if it exists */
4828 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4837 for (i
= 0; i
< blob
->cbData
; i
++)
4839 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4848 SetLastError(CRYPT_E_ASN1_BADTAG
);
4854 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4855 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4856 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4864 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4865 lpszStructType
, pbEncoded
, cbEncoded
,
4866 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4869 *pcbStructInfo
= bytesNeeded
;
4870 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4871 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4873 CRYPT_INTEGER_BLOB
*blob
;
4875 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4876 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4877 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4878 blob
->pbData
= (BYTE
*)pvStructInfo
+
4879 sizeof(CRYPT_INTEGER_BLOB
);
4880 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4881 lpszStructType
, pbEncoded
, cbEncoded
,
4882 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4887 _SEH_EXCEPT(page_fault
)
4889 SetLastError(STATUS_ACCESS_VIOLATION
);
4896 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4897 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4898 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4904 *pcbStructInfo
= sizeof(int);
4909 if (pbEncoded
[0] == ASN_ENUMERATED
)
4911 unsigned int val
= 0, i
;
4915 SetLastError(CRYPT_E_ASN1_EOD
);
4918 else if (pbEncoded
[1] == 0)
4920 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4925 /* A little strange looking, but we have to accept a sign byte:
4926 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4927 * assuming a small length is okay here, it has to be in short
4930 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4932 SetLastError(CRYPT_E_ASN1_LARGE
);
4935 for (i
= 0; i
< pbEncoded
[1]; i
++)
4938 val
|= pbEncoded
[2 + i
];
4940 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4941 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4943 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4944 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4945 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4951 SetLastError(CRYPT_E_ASN1_BADTAG
);
4955 _SEH_EXCEPT(page_fault
)
4957 SetLastError(STATUS_ACCESS_VIOLATION
);
4964 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4967 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4972 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4974 if (!isdigit(*(pbEncoded))) \
4976 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4982 (word) += *(pbEncoded)++ - '0'; \
4987 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
4988 SYSTEMTIME
*sysTime
)
4995 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
4997 WORD hours
, minutes
= 0;
4998 BYTE sign
= *pbEncoded
++;
5001 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
5002 if (ret
&& hours
>= 24)
5004 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5009 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
5010 if (ret
&& minutes
>= 60)
5012 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5020 sysTime
->wHour
+= hours
;
5021 sysTime
->wMinute
+= minutes
;
5025 if (hours
> sysTime
->wHour
)
5028 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
5031 sysTime
->wHour
-= hours
;
5032 if (minutes
> sysTime
->wMinute
)
5035 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
5038 sysTime
->wMinute
-= minutes
;
5043 _SEH_EXCEPT(page_fault
)
5045 SetLastError(STATUS_ACCESS_VIOLATION
);
5052 #define MIN_ENCODED_TIME_LENGTH 10
5054 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
5055 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5056 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5062 *pcbStructInfo
= sizeof(FILETIME
);
5068 if (pbEncoded
[0] == ASN_UTCTIME
)
5072 SetLastError(CRYPT_E_ASN1_EOD
);
5075 else if (pbEncoded
[1] > 0x7f)
5077 /* long-form date strings really can't be valid */
5078 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5083 SYSTEMTIME sysTime
= { 0 };
5084 BYTE len
= pbEncoded
[1];
5086 if (len
< MIN_ENCODED_TIME_LENGTH
)
5088 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5094 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
5095 if (sysTime
.wYear
>= 50)
5096 sysTime
.wYear
+= 1900;
5098 sysTime
.wYear
+= 2000;
5099 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5100 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5101 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5102 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
5105 if (len
>= 2 && isdigit(*pbEncoded
) &&
5106 isdigit(*(pbEncoded
+ 1)))
5107 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5109 else if (isdigit(*pbEncoded
))
5110 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
5113 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5116 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5117 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5120 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5121 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5122 ret
= SystemTimeToFileTime(&sysTime
,
5123 (FILETIME
*)pvStructInfo
);
5130 SetLastError(CRYPT_E_ASN1_BADTAG
);
5134 _SEH_EXCEPT(page_fault
)
5136 SetLastError(STATUS_ACCESS_VIOLATION
);
5143 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
5144 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5145 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5151 *pcbStructInfo
= sizeof(FILETIME
);
5157 if (pbEncoded
[0] == ASN_GENERALTIME
)
5161 SetLastError(CRYPT_E_ASN1_EOD
);
5164 else if (pbEncoded
[1] > 0x7f)
5166 /* long-form date strings really can't be valid */
5167 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5172 BYTE len
= pbEncoded
[1];
5174 if (len
< MIN_ENCODED_TIME_LENGTH
)
5176 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5181 SYSTEMTIME sysTime
= { 0 };
5184 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
5185 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5186 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5187 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5190 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5193 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5195 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
5202 /* workaround macro weirdness */
5203 digits
= min(len
, 3);
5204 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
5205 sysTime
.wMilliseconds
);
5208 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5211 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5212 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5215 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5216 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5217 ret
= SystemTimeToFileTime(&sysTime
,
5218 (FILETIME
*)pvStructInfo
);
5225 SetLastError(CRYPT_E_ASN1_BADTAG
);
5229 _SEH_EXCEPT(page_fault
)
5231 SetLastError(STATUS_ACCESS_VIOLATION
);
5238 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5239 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5240 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5246 if (pbEncoded
[0] == ASN_UTCTIME
)
5247 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5248 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5250 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5251 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5252 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5253 pvStructInfo
, pcbStructInfo
);
5256 SetLastError(CRYPT_E_ASN1_BADTAG
);
5260 _SEH_EXCEPT(page_fault
)
5262 SetLastError(STATUS_ACCESS_VIOLATION
);
5269 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5270 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5271 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5277 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5279 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5281 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5286 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5287 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5289 ptr
= pbEncoded
+ 1 + lenBytes
;
5290 remainingLen
= dataLen
;
5291 while (ret
&& remainingLen
)
5295 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5298 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5300 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5301 ptr
+= 1 + nextLenBytes
+ nextLen
;
5302 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5303 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5304 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5310 CRYPT_SEQUENCE_OF_ANY
*seq
;
5314 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5315 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5317 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5318 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5319 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5320 seq
->cValue
= cValue
;
5321 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5323 nextPtr
= (BYTE
*)seq
->rgValue
+
5324 cValue
* sizeof(CRYPT_DER_BLOB
);
5325 ptr
= pbEncoded
+ 1 + lenBytes
;
5326 remainingLen
= dataLen
;
5328 while (ret
&& remainingLen
)
5332 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5335 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5337 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5339 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5340 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5343 seq
->rgValue
[i
].pbData
= nextPtr
;
5344 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5346 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5348 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5349 ptr
+= 1 + nextLenBytes
+ nextLen
;
5359 SetLastError(CRYPT_E_ASN1_BADTAG
);
5363 _SEH_EXCEPT(page_fault
)
5365 SetLastError(STATUS_ACCESS_VIOLATION
);
5372 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5373 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5374 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5378 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5380 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5381 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5382 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5384 if (!pvStructInfo
&& !pcbStructInfo
)
5386 SetLastError(ERROR_INVALID_PARAMETER
);
5389 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5390 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5392 SetLastError(ERROR_FILE_NOT_FOUND
);
5397 SetLastError(CRYPT_E_ASN1_EOD
);
5400 if (cbEncoded
> MAX_ENCODED_LEN
)
5402 SetLastError(CRYPT_E_ASN1_LARGE
);
5406 SetLastError(NOERROR
);
5407 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5408 *(BYTE
**)pvStructInfo
= NULL
;
5409 if (!HIWORD(lpszStructType
))
5411 switch (LOWORD(lpszStructType
))
5413 case (WORD
)X509_CERT
:
5414 decodeFunc
= CRYPT_AsnDecodeCert
;
5416 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5417 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5419 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5420 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5422 case (WORD
)X509_EXTENSIONS
:
5423 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5425 case (WORD
)X509_NAME
:
5426 decodeFunc
= CRYPT_AsnDecodeName
;
5428 case (WORD
)X509_PUBLIC_KEY_INFO
:
5429 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5431 case (WORD
)X509_ALTERNATE_NAME
:
5432 decodeFunc
= CRYPT_AsnDecodeAltName
;
5434 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5435 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5437 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5438 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5440 case (WORD
)X509_OCTET_STRING
:
5441 decodeFunc
= CRYPT_AsnDecodeOctets
;
5443 case (WORD
)X509_BITS
:
5444 case (WORD
)X509_KEY_USAGE
:
5445 decodeFunc
= CRYPT_AsnDecodeBits
;
5447 case (WORD
)X509_INTEGER
:
5448 decodeFunc
= CRYPT_AsnDecodeInt
;
5450 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5451 decodeFunc
= CRYPT_AsnDecodeInteger
;
5453 case (WORD
)X509_MULTI_BYTE_UINT
:
5454 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5456 case (WORD
)X509_ENUMERATED
:
5457 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5459 case (WORD
)X509_CHOICE_OF_TIME
:
5460 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5462 case (WORD
)X509_SEQUENCE_OF_ANY
:
5463 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5465 case (WORD
)PKCS_UTC_TIME
:
5466 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5469 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5472 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5473 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5474 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5475 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5476 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5477 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5478 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5479 decodeFunc
= CRYPT_AsnDecodeBits
;
5480 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5481 decodeFunc
= CRYPT_AsnDecodeOctets
;
5482 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5483 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5484 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5485 decodeFunc
= CRYPT_AsnDecodeAltName
;
5486 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5487 decodeFunc
= CRYPT_AsnDecodeAltName
;
5488 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5489 decodeFunc
= CRYPT_AsnDecodeAltName
;
5490 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5491 decodeFunc
= CRYPT_AsnDecodeAltName
;
5492 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5493 decodeFunc
= CRYPT_AsnDecodeAltName
;
5495 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5496 debugstr_a(lpszStructType
));
5498 decodeFunc
= (CryptDecodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
5499 lpszStructType
, CRYPT_OID_DECODE_OBJECT_EX_FUNC
, &lib
);
5501 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5502 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5504 SetLastError(ERROR_FILE_NOT_FOUND
);
5510 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5511 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5513 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5514 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5517 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5518 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5519 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5524 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5525 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5528 if (!pszPublicKeyObjId
)
5529 pszPublicKeyObjId
= szOID_RSA_RSA
;
5530 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5534 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5537 LPBYTE pubKey
= CryptMemAlloc(keySize
);
5541 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
5545 DWORD encodedLen
= 0;
5547 ret
= CryptEncodeObject(dwCertEncodingType
,
5548 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5551 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5552 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5555 *pcbInfo
= sizeNeeded
;
5556 else if (*pcbInfo
< sizeNeeded
)
5558 SetLastError(ERROR_MORE_DATA
);
5559 *pcbInfo
= sizeNeeded
;
5564 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5565 sizeof(CERT_PUBLIC_KEY_INFO
);
5566 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5568 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5569 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5570 pInfo
->PublicKey
.pbData
=
5571 (BYTE
*)pInfo
->Algorithm
.pszObjId
5572 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5573 pInfo
->PublicKey
.cbData
= encodedLen
;
5574 pInfo
->PublicKey
.cUnusedBits
= 0;
5575 ret
= CryptEncodeObject(dwCertEncodingType
,
5576 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5577 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5581 CryptMemFree(pubKey
);
5586 CryptDestroyKey(key
);
5591 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5592 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5593 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5595 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5596 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5597 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5600 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5603 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5604 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5609 SetLastError(ERROR_INVALID_PARAMETER
);
5613 if (pszPublicKeyObjId
)
5614 exportFunc
= CRYPT_GetFunc(dwCertEncodingType
, pszPublicKeyObjId
,
5615 CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
, &lib
);
5617 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
5618 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5619 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5625 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5626 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5628 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5632 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5633 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5634 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5637 DWORD pubKeySize
= 0;
5639 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5640 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5642 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5643 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5646 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
5650 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5651 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5654 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5656 CryptMemFree(pubKey
);
5664 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5665 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5666 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5668 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5669 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5670 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5673 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5676 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5677 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5679 importFunc
= CRYPT_GetFunc(dwCertEncodingType
, pInfo
->Algorithm
.pszObjId
,
5680 CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, &lib
);
5682 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
5683 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,