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
43 #include "wine/debug.h"
44 #include "wine/exception.h"
46 /* This is a bit arbitrary, but to set some limit: */
47 #define MAX_ENCODED_LEN 0x02000000
49 /* a few asn.1 tags we need */
50 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
51 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
52 #define ASN_OCTETSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x04)
53 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
54 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
55 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
56 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
57 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
58 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
59 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
61 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
63 static const WCHAR szDllName
[] = { 'D','l','l',0 };
65 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
66 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
67 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
68 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
69 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
70 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
71 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
72 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
73 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
74 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
75 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
76 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
78 /* filter for page-fault exceptions */
79 static WINE_EXCEPTION_FILTER(page_fault
)
81 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
82 return EXCEPTION_EXECUTE_HANDLER
;
83 return EXCEPTION_CONTINUE_SEARCH
;
86 static char *CRYPT_GetKeyName(DWORD dwEncodingType
, LPCSTR pszFuncName
,
89 static const char szEncodingTypeFmt
[] =
90 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %ld\\%s\\%s";
92 char numericOID
[7]; /* enough for "#65535" */
96 /* MSDN says the encoding type is a mask, but it isn't treated that way.
97 * (E.g., if dwEncodingType were 3, the key names "EncodingType 1" and
98 * "EncodingType 2" would be expected if it were a mask. Instead native
99 * stores values in "EncodingType 3".
103 snprintf(numericOID
, sizeof(numericOID
), "#%d", (int)pszOID
);
109 /* This is enough: the lengths of the two string parameters are explicitly
110 * counted, and we need up to five additional characters for the encoding
111 * type. These are covered by the "%d", "%s", and "%s" characters in the
112 * format specifier that are removed by sprintf.
114 len
= sizeof(szEncodingTypeFmt
) + lstrlenA(pszFuncName
) + lstrlenA(oid
);
115 szKey
= HeapAlloc(GetProcessHeap(), 0, len
);
117 sprintf(szKey
, szEncodingTypeFmt
, dwEncodingType
, pszFuncName
, oid
);
121 BOOL WINAPI
CryptRegisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
122 LPCSTR pszOID
, LPCWSTR pwszDll
, LPCSTR pszOverrideFuncName
)
128 TRACE("%lx %s %s %s %s\n", dwEncodingType
, pszFuncName
, pszOID
,
129 debugstr_w(pwszDll
), pszOverrideFuncName
);
131 /* This only registers functions for encoding certs, not messages */
132 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
135 /* Native does nothing pwszDll is NULL */
139 /* I'm not matching MS bug for bug here, because I doubt any app depends on
141 * - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
142 * it creates would never be used
143 * - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
144 * Instead I disallow both of these with ERROR_INVALID_PARAMETER.
146 if (!pszFuncName
|| !pszOID
)
148 SetLastError(ERROR_INVALID_PARAMETER
);
152 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
153 TRACE("Key name is %s\n", debugstr_a(szKey
));
158 r
= RegCreateKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
159 HeapFree(GetProcessHeap(), 0, szKey
);
160 if(r
!= ERROR_SUCCESS
)
163 /* write the values */
164 if (pszOverrideFuncName
)
165 RegSetValueExA(hKey
, "FuncName", 0, REG_SZ
, pszOverrideFuncName
,
166 lstrlenA(pszOverrideFuncName
) + 1);
167 RegSetValueExW(hKey
, szDllName
, 0, REG_SZ
, (const BYTE
*) pwszDll
,
168 (lstrlenW(pwszDll
) + 1) * sizeof (WCHAR
));
174 BOOL WINAPI
CryptUnregisterOIDFunction(DWORD dwEncodingType
, LPCSTR pszFuncName
,
180 TRACE("%lx %s %s\n", dwEncodingType
, pszFuncName
, pszOID
);
182 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
185 if (!pszFuncName
|| !pszOID
)
187 SetLastError(ERROR_INVALID_PARAMETER
);
191 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
192 rc
= RegDeleteKeyA(HKEY_LOCAL_MACHINE
, szKey
);
193 HeapFree(GetProcessHeap(), 0, szKey
);
196 return rc
? FALSE
: TRUE
;
199 BOOL WINAPI
CryptGetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
200 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD
*pdwValueType
, BYTE
*pbValueData
,
207 TRACE("%lx %s %s %s %p %p %p\n", dwEncodingType
, debugstr_a(pszFuncName
),
208 debugstr_a(pszOID
), debugstr_w(pwszValueName
), pdwValueType
, pbValueData
,
211 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
214 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
216 SetLastError(ERROR_INVALID_PARAMETER
);
220 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
221 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
222 HeapFree(GetProcessHeap(), 0, szKey
);
227 rc
= RegQueryValueExW(hKey
, pwszValueName
, NULL
, pdwValueType
,
228 pbValueData
, pcbValueData
);
233 return rc
? FALSE
: TRUE
;
236 BOOL WINAPI
CryptSetOIDFunctionValue(DWORD dwEncodingType
, LPCSTR pszFuncName
,
237 LPCSTR pszOID
, LPCWSTR pwszValueName
, DWORD dwValueType
,
238 const BYTE
*pbValueData
, DWORD cbValueData
)
244 TRACE("%lx %s %s %s %ld %p %ld\n", dwEncodingType
, debugstr_a(pszFuncName
),
245 debugstr_a(pszOID
), debugstr_w(pwszValueName
), dwValueType
, pbValueData
,
248 if (!GET_CERT_ENCODING_TYPE(dwEncodingType
))
251 if (!pszFuncName
|| !pszOID
|| !pwszValueName
)
253 SetLastError(ERROR_INVALID_PARAMETER
);
257 szKey
= CRYPT_GetKeyName(dwEncodingType
, pszFuncName
, pszOID
);
258 rc
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
259 HeapFree(GetProcessHeap(), 0, szKey
);
264 rc
= RegSetValueExW(hKey
, pwszValueName
, 0, dwValueType
, pbValueData
,
270 return rc
? FALSE
: TRUE
;
273 /* Gets the registered function named szFuncName for dwCertEncodingType and
274 * lpszStructType, or NULL if one could not be found. *lib will be set to the
275 * handle of the module it's in, or NULL if no module was loaded. If the
276 * return value is NULL, *lib will also be NULL, to simplify error handling.
278 static void *CRYPT_GetFunc(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
279 LPCSTR szFuncName
, HMODULE
*lib
)
282 char *szKey
= CRYPT_GetKeyName(dwCertEncodingType
, szFuncName
,
284 const char *funcName
;
287 DWORD type
, size
= 0;
289 TRACE("(%08lx %s %s %p)\n", dwCertEncodingType
, debugstr_a(lpszStructType
),
290 debugstr_a(szFuncName
), lib
);
293 r
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, szKey
, &hKey
);
294 HeapFree(GetProcessHeap(), 0, szKey
);
295 if(r
!= ERROR_SUCCESS
)
298 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, NULL
, &size
);
299 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
301 funcName
= HeapAlloc(GetProcessHeap(), 0, size
);
302 RegQueryValueExA(hKey
, "FuncName", NULL
, &type
, (LPBYTE
)funcName
,
306 funcName
= szFuncName
;
307 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, NULL
, &size
);
308 if (GetLastError() == ERROR_MORE_DATA
&& type
== REG_SZ
)
310 LPWSTR dllName
= HeapAlloc(GetProcessHeap(), 0, size
);
312 RegQueryValueExW(hKey
, szDllName
, NULL
, &type
, (LPBYTE
)dllName
,
314 *lib
= LoadLibraryW(dllName
);
317 ret
= GetProcAddress(*lib
, funcName
);
320 /* Unload the library, the caller doesn't want to unload it
321 * when the return value is NULL.
327 HeapFree(GetProcessHeap(), 0, dllName
);
329 if (funcName
!= szFuncName
)
330 HeapFree(GetProcessHeap(), 0, (char *)funcName
);
331 TRACE("returning %p\n", ret
);
335 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
338 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
339 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
343 CryptEncodeObjectFunc pCryptEncodeObject
;
345 TRACE("(0x%08lx, %s, %p, %p, %p)\n",
346 dwCertEncodingType
, HIWORD(lpszStructType
) ? debugstr_a(lpszStructType
) :
347 "(integer value)", pvStructInfo
, pbEncoded
, pcbEncoded
);
349 if (!pbEncoded
&& !pcbEncoded
)
351 SetLastError(ERROR_INVALID_PARAMETER
);
355 /* Try registered DLL first.. */
357 (CryptEncodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
358 lpszStructType
, "CryptEncodeObject", &lib
);
359 if (pCryptEncodeObject
)
361 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
362 pvStructInfo
, pbEncoded
, pcbEncoded
);
367 /* If not, use CryptEncodeObjectEx */
368 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
369 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
374 /* Helper function to check *pcbEncoded, set it to the required size, and
375 * optionally to allocate memory. Assumes pbEncoded is not NULL.
376 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
377 * pointer to the newly allocated memory.
379 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
380 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
385 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
387 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
388 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
390 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
391 if (!*(BYTE
**)pbEncoded
)
394 *pcbEncoded
= bytesNeeded
;
396 else if (bytesNeeded
> *pcbEncoded
)
398 *pcbEncoded
= bytesNeeded
;
399 SetLastError(ERROR_MORE_DATA
);
405 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
407 DWORD bytesNeeded
, significantBytes
= 0;
415 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
416 temp
<<= 8, significantBytes
--)
418 bytesNeeded
= significantBytes
+ 1;
422 *pcbEncoded
= bytesNeeded
;
425 if (*pcbEncoded
< bytesNeeded
)
427 SetLastError(ERROR_MORE_DATA
);
431 *pbEncoded
= (BYTE
)len
;
436 *pbEncoded
++ = significantBytes
| 0x80;
437 for (i
= 0; i
< significantBytes
; i
++)
439 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
443 *pcbEncoded
= bytesNeeded
;
447 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
448 LPCSTR pszObjId
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
450 DWORD bytesNeeded
= 0, lenBytes
;
460 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
462 SetLastError(CRYPT_E_ASN1_ERROR
);
466 firstByte
= val1
* 40 + val2
;
467 ptr
= pszObjId
+ firstPos
;
472 /* note I assume each component is at most 32-bits long in base 2 */
473 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
475 if (val1
>= 0x10000000)
477 else if (val1
>= 0x200000)
479 else if (val1
>= 0x4000)
481 else if (val1
>= 0x80)
491 SetLastError(CRYPT_E_ASN1_ERROR
);
495 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
499 bytesNeeded
+= 1 + lenBytes
;
502 if (*pbEncoded
< bytesNeeded
)
504 SetLastError(ERROR_MORE_DATA
);
509 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
510 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
511 pbEncoded
+= lenBytes
;
517 *pbEncoded
++ = firstByte
;
518 ptr
= pszObjId
+ firstPos
;
521 sscanf(ptr
, "%d%n", &val
, &pos
);
523 unsigned char outBytes
[5];
526 if (val
>= 0x10000000)
528 else if (val
>= 0x200000)
530 else if (val
>= 0x4000)
532 else if (val
>= 0x80)
536 for (i
= numBytes
; i
> 0; i
--)
538 outBytes
[i
- 1] = val
& 0x7f;
541 for (i
= 0; i
< numBytes
- 1; i
++)
542 *pbEncoded
++ = outBytes
[i
] | 0x80;
543 *pbEncoded
++ = outBytes
[i
];
552 *pcbEncoded
= bytesNeeded
;
556 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
557 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
560 DWORD bytesNeeded
, lenBytes
, encodedLen
;
563 switch (value
->dwValueType
)
565 case CERT_RDN_NUMERIC_STRING
:
566 tag
= ASN_NUMERICSTRING
;
567 encodedLen
= value
->Value
.cbData
;
569 case CERT_RDN_PRINTABLE_STRING
:
570 tag
= ASN_PRINTABLESTRING
;
571 encodedLen
= value
->Value
.cbData
;
573 case CERT_RDN_IA5_STRING
:
575 encodedLen
= value
->Value
.cbData
;
577 case CERT_RDN_ANY_TYPE
:
578 /* explicitly disallowed */
579 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
582 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
585 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
586 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
589 if (*pcbEncoded
< bytesNeeded
)
591 SetLastError(ERROR_MORE_DATA
);
597 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
598 pbEncoded
+= lenBytes
;
599 switch (value
->dwValueType
)
601 case CERT_RDN_NUMERIC_STRING
:
602 case CERT_RDN_PRINTABLE_STRING
:
603 case CERT_RDN_IA5_STRING
:
604 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
608 *pcbEncoded
= bytesNeeded
;
612 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
613 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
615 DWORD bytesNeeded
= 0, lenBytes
, size
;
618 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, attr
->pszObjId
, NULL
, &size
);
622 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
623 * with dwValueType, so "cast" it to get its encoded size
625 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
626 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
630 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
631 bytesNeeded
+= 1 + lenBytes
;
634 if (*pcbEncoded
< bytesNeeded
)
636 SetLastError(ERROR_MORE_DATA
);
641 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SEQUENCE
;
642 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
644 pbEncoded
+= lenBytes
;
645 size
= bytesNeeded
- 1 - lenBytes
;
646 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, attr
->pszObjId
,
651 size
= bytesNeeded
- 1 - lenBytes
- size
;
652 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
653 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
658 *pcbEncoded
= bytesNeeded
;
664 static int BLOBComp(const void *l
, const void *r
)
666 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
669 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
670 ret
= a
->cbData
- b
->cbData
;
674 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
676 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
677 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
680 CRYPT_DER_BLOB
*blobs
= NULL
;
684 DWORD bytesNeeded
= 0, lenBytes
, i
;
689 blobs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
690 rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
694 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
696 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
697 NULL
, &blobs
[i
].cbData
);
699 bytesNeeded
+= blobs
[i
].cbData
;
703 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
704 bytesNeeded
+= 1 + lenBytes
;
707 if (*pcbEncoded
< bytesNeeded
)
709 SetLastError(ERROR_MORE_DATA
);
714 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
716 blobs
[i
].pbData
= HeapAlloc(GetProcessHeap(), 0,
718 if (!blobs
[i
].pbData
)
721 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
722 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
727 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
729 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
730 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
732 pbEncoded
+= lenBytes
;
733 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
735 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
736 pbEncoded
+= blobs
[i
].cbData
;
741 *pcbEncoded
= bytesNeeded
;
745 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
746 HeapFree(GetProcessHeap(), 0, blobs
[i
].pbData
);
751 SetLastError(STATUS_ACCESS_VIOLATION
);
755 HeapFree(GetProcessHeap(), 0, blobs
);
759 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
760 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
761 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
767 CERT_NAME_INFO
*info
= (CERT_NAME_INFO
*)pvStructInfo
;
768 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
770 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
772 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
774 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
779 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
780 bytesNeeded
+= 1 + lenBytes
;
784 *pcbEncoded
= bytesNeeded
;
787 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
788 pbEncoded
, pcbEncoded
, bytesNeeded
)))
790 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
791 pbEncoded
= *(BYTE
**)pbEncoded
;
792 *pbEncoded
++ = ASN_SEQUENCEOF
;
793 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
795 pbEncoded
+= lenBytes
;
796 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
799 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
800 &info
->rgRDN
[i
], pbEncoded
, &size
);
813 SetLastError(STATUS_ACCESS_VIOLATION
);
820 static BOOL
CRYPT_EncodeBool(BOOL val
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
830 SetLastError(ERROR_MORE_DATA
);
834 *pbEncoded
++ = ASN_BOOL
;
836 *pbEncoded
++ = val
? 0xff : 0;
840 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
841 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
842 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
848 CERT_BASIC_CONSTRAINTS2_INFO
*info
=
849 (CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
850 DWORD bytesNeeded
= 0, lenBytes
, caLen
= 0, pathConstraintLen
= 0;
855 ret
= CRYPT_EncodeBool(TRUE
, NULL
, &caLen
);
857 bytesNeeded
+= caLen
;
859 if (info
->fPathLenConstraint
)
861 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
,
862 &info
->dwPathLenConstraint
, 0, NULL
, NULL
, &pathConstraintLen
);
864 bytesNeeded
+= pathConstraintLen
;
868 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
869 bytesNeeded
+= 1 + lenBytes
;
872 *pcbEncoded
= bytesNeeded
;
877 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
878 pbEncoded
, pcbEncoded
, bytesNeeded
)))
880 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
881 pbEncoded
= *(BYTE
**)pbEncoded
;
882 *pbEncoded
++ = ASN_SEQUENCE
;
883 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
,
885 pbEncoded
+= lenBytes
;
888 ret
= CRYPT_EncodeBool(TRUE
, pbEncoded
, &caLen
);
892 if (info
->fPathLenConstraint
)
894 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
,
895 X509_INTEGER
, &info
->dwPathLenConstraint
, 0, NULL
,
896 pbEncoded
, &pathConstraintLen
);
904 SetLastError(STATUS_ACCESS_VIOLATION
);
911 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
912 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
913 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
919 CRYPT_DATA_BLOB
*blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
920 DWORD bytesNeeded
, lenBytes
;
922 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
923 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
926 *pcbEncoded
= bytesNeeded
;
931 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
932 pcbEncoded
, bytesNeeded
)))
934 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
935 pbEncoded
= *(BYTE
**)pbEncoded
;
936 *pbEncoded
++ = ASN_OCTETSTRING
;
937 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
938 pbEncoded
+= lenBytes
;
940 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
946 SetLastError(STATUS_ACCESS_VIOLATION
);
953 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
954 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
955 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
961 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
962 DWORD bytesNeeded
, lenBytes
, dataBytes
;
965 /* yep, MS allows cUnusedBits to be >= 8 */
966 if (blob
->cbData
* 8 > blob
->cUnusedBits
)
968 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
969 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
977 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
978 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
981 *pcbEncoded
= bytesNeeded
;
986 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
987 pcbEncoded
, bytesNeeded
)))
989 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
990 pbEncoded
= *(BYTE
**)pbEncoded
;
991 *pbEncoded
++ = ASN_BITSTRING
;
992 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
993 pbEncoded
+= lenBytes
;
994 *pbEncoded
++ = unusedBits
;
997 BYTE mask
= 0xff << unusedBits
;
1001 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1002 pbEncoded
+= dataBytes
- 1;
1004 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1009 __EXCEPT(page_fault
)
1011 SetLastError(STATUS_ACCESS_VIOLATION
);
1018 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1019 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1020 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1022 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1024 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1025 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1028 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1029 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1030 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1036 DWORD significantBytes
, lenBytes
;
1037 BYTE padByte
= 0, bytesNeeded
;
1039 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1041 significantBytes
= blob
->cbData
;
1042 if (significantBytes
)
1044 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1046 /* negative, lop off leading (little-endian) 0xffs */
1047 for (; significantBytes
> 0 &&
1048 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1050 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1058 /* positive, lop off leading (little-endian) zeroes */
1059 for (; significantBytes
> 0 &&
1060 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1062 if (significantBytes
== 0)
1063 significantBytes
= 1;
1064 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1072 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1074 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1075 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1080 *pcbEncoded
= bytesNeeded
;
1085 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1086 pcbEncoded
, bytesNeeded
)))
1088 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1089 pbEncoded
= *(BYTE
**)pbEncoded
;
1090 *pbEncoded
++ = ASN_INTEGER
;
1093 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1094 pbEncoded
+= lenBytes
;
1095 *pbEncoded
++ = padByte
;
1099 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1100 pbEncoded
+= lenBytes
;
1102 for (; significantBytes
> 0; significantBytes
--)
1103 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1107 __EXCEPT(page_fault
)
1109 SetLastError(STATUS_ACCESS_VIOLATION
);
1116 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1117 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1118 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1124 DWORD significantBytes
, lenBytes
;
1127 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1129 significantBytes
= blob
->cbData
;
1130 if (significantBytes
)
1132 /* positive, lop off leading (little-endian) zeroes */
1133 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
1136 if (significantBytes
== 0)
1137 significantBytes
= 1;
1138 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1142 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1144 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1145 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1150 *pcbEncoded
= bytesNeeded
;
1155 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1156 pcbEncoded
, bytesNeeded
)))
1158 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1159 pbEncoded
= *(BYTE
**)pbEncoded
;
1160 *pbEncoded
++ = ASN_INTEGER
;
1163 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1164 pbEncoded
+= lenBytes
;
1169 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1170 pbEncoded
+= lenBytes
;
1172 for (; significantBytes
> 0; significantBytes
--)
1173 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1177 __EXCEPT(page_fault
)
1179 SetLastError(STATUS_ACCESS_VIOLATION
);
1186 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
1187 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1188 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1190 CRYPT_INTEGER_BLOB blob
;
1193 /* Encode as an unsigned integer, then change the tag to enumerated */
1194 blob
.cbData
= sizeof(DWORD
);
1195 blob
.pbData
= (BYTE
*)pvStructInfo
;
1196 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
1197 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1198 if (ret
&& pbEncoded
)
1200 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1201 pbEncoded
= *(BYTE
**)pbEncoded
;
1202 pbEncoded
[0] = ASN_ENUMERATED
;
1207 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
1208 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1209 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1216 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1217 * temporary buffer because the output buffer is not NULL-terminated.
1220 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1224 *pcbEncoded
= bytesNeeded
;
1229 /* Sanity check the year, this is a two-digit year format */
1230 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1232 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
1234 SetLastError(CRYPT_E_BAD_ENCODE
);
1239 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1240 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1242 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1243 pbEncoded
= *(BYTE
**)pbEncoded
;
1244 buf
[0] = ASN_UTCTIME
;
1245 buf
[1] = bytesNeeded
- 2;
1246 snprintf(buf
+ 2, sizeof(buf
) - 2,
1247 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
1248 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
1249 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
1250 sysTime
.wMinute
, sysTime
.wSecond
);
1251 memcpy(pbEncoded
, buf
, bytesNeeded
);
1256 __EXCEPT(page_fault
)
1258 SetLastError(STATUS_ACCESS_VIOLATION
);
1265 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
1266 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1267 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1274 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1275 * temporary buffer because the output buffer is not NULL-terminated.
1278 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1282 *pcbEncoded
= bytesNeeded
;
1287 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1290 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1291 pcbEncoded
, bytesNeeded
);
1294 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1295 pbEncoded
= *(BYTE
**)pbEncoded
;
1296 buf
[0] = ASN_GENERALTIME
;
1297 buf
[1] = bytesNeeded
- 2;
1298 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
1299 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
1300 sysTime
.wMinute
, sysTime
.wSecond
);
1301 memcpy(pbEncoded
, buf
, bytesNeeded
);
1305 __EXCEPT(page_fault
)
1307 SetLastError(STATUS_ACCESS_VIOLATION
);
1314 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
1315 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1316 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1324 /* Check the year, if it's in the UTCTime range call that encode func */
1325 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
1327 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
1328 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
1329 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1331 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
1332 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1335 __EXCEPT(page_fault
)
1337 SetLastError(STATUS_ACCESS_VIOLATION
);
1344 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
1345 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1346 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1352 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1353 CRYPT_SEQUENCE_OF_ANY
*seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
1355 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
1356 dataLen
+= seq
->rgValue
[i
].cbData
;
1357 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1358 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1361 *pcbEncoded
= bytesNeeded
;
1366 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1367 pcbEncoded
, bytesNeeded
)))
1369 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1370 pbEncoded
= *(BYTE
**)pbEncoded
;
1371 *pbEncoded
++ = ASN_SEQUENCEOF
;
1372 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1373 pbEncoded
+= lenBytes
;
1374 for (i
= 0; i
< seq
->cValue
; i
++)
1376 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
1377 seq
->rgValue
[i
].cbData
);
1378 pbEncoded
+= seq
->rgValue
[i
].cbData
;
1383 __EXCEPT(page_fault
)
1385 SetLastError(STATUS_ACCESS_VIOLATION
);
1392 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
1393 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
1395 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
1396 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
1397 void *pvEncoded
, DWORD
*pcbEncoded
)
1401 CryptEncodeObjectExFunc encodeFunc
= NULL
;
1403 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n",
1404 dwCertEncodingType
, HIWORD(lpszStructType
) ? debugstr_a(lpszStructType
) :
1405 "(integer value)", pvStructInfo
, dwFlags
, pEncodePara
, pvEncoded
,
1408 if (!pvEncoded
&& !pcbEncoded
)
1410 SetLastError(ERROR_INVALID_PARAMETER
);
1413 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
1414 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
1416 SetLastError(ERROR_FILE_NOT_FOUND
);
1420 SetLastError(NOERROR
);
1421 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
1422 *(BYTE
**)pvEncoded
= NULL
;
1423 if (!HIWORD(lpszStructType
))
1425 switch (LOWORD(lpszStructType
))
1427 case (WORD
)X509_NAME
:
1428 encodeFunc
= CRYPT_AsnEncodeName
;
1430 case (WORD
)X509_BASIC_CONSTRAINTS2
:
1431 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
1433 case (WORD
)X509_OCTET_STRING
:
1434 encodeFunc
= CRYPT_AsnEncodeOctets
;
1436 case (WORD
)X509_BITS
:
1437 case (WORD
)X509_KEY_USAGE
:
1438 encodeFunc
= CRYPT_AsnEncodeBits
;
1440 case (WORD
)X509_INTEGER
:
1441 encodeFunc
= CRYPT_AsnEncodeInt
;
1443 case (WORD
)X509_MULTI_BYTE_INTEGER
:
1444 encodeFunc
= CRYPT_AsnEncodeInteger
;
1446 case (WORD
)X509_MULTI_BYTE_UINT
:
1447 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
1449 case (WORD
)X509_ENUMERATED
:
1450 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
1452 case (WORD
)X509_CHOICE_OF_TIME
:
1453 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
1455 case (WORD
)X509_SEQUENCE_OF_ANY
:
1456 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
1458 case (WORD
)PKCS_UTC_TIME
:
1459 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
1462 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
1465 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
1466 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
1467 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
1468 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
1469 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
1470 encodeFunc
= CRYPT_AsnEncodeBits
;
1471 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
1472 encodeFunc
= CRYPT_AsnEncodeOctets
;
1473 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
1474 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
1476 TRACE("OID %s not found or unimplemented, looking for DLL\n",
1477 debugstr_a(lpszStructType
));
1479 encodeFunc
= (CryptEncodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
1480 lpszStructType
, "CryptEncodeObjectEx", &lib
);
1482 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
1483 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
1485 SetLastError(ERROR_FILE_NOT_FOUND
);
1491 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1492 DWORD
, DWORD
, void *, DWORD
*);
1494 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
1495 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
1496 DWORD
*pcbStructInfo
)
1500 CryptDecodeObjectFunc pCryptDecodeObject
;
1502 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n",
1503 dwCertEncodingType
, HIWORD(lpszStructType
) ? debugstr_a(lpszStructType
) :
1504 "(integer value)", pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1507 if (!pvStructInfo
&& !pcbStructInfo
)
1509 SetLastError(ERROR_INVALID_PARAMETER
);
1513 /* Try registered DLL first.. */
1514 pCryptDecodeObject
=
1515 (CryptDecodeObjectFunc
)CRYPT_GetFunc(dwCertEncodingType
,
1516 lpszStructType
, "CryptDecodeObject", &lib
);
1517 if (pCryptDecodeObject
)
1519 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
1520 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1525 /* If not, use CryptDecodeObjectEx */
1526 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
1527 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
1532 /* Gets the number of length bytes from the given (leading) length byte */
1533 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1535 /* Helper function to get the encoded length of the data starting at pbEncoded,
1536 * where pbEncoded[0] is the tag. If the data are too short to contain a
1537 * length or if the length is too large for cbEncoded, sets an appropriate
1538 * error code and returns FALSE.
1540 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1547 SetLastError(CRYPT_E_ASN1_EOD
);
1550 else if (pbEncoded
[1] <= 0x7f)
1552 *len
= pbEncoded
[1];
1557 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
1559 if (lenLen
> sizeof(DWORD
) + 1)
1561 SetLastError(CRYPT_E_ASN1_LARGE
);
1564 else if (lenLen
+ 2 > cbEncoded
)
1566 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1577 out
|= *pbEncoded
++;
1579 if (out
+ lenLen
+ 1 > cbEncoded
)
1581 SetLastError(CRYPT_E_ASN1_EOD
);
1594 /* Helper function to check *pcbStructInfo, set it to the required size, and
1595 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
1596 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
1597 * pointer to the newly allocated memory.
1599 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
1600 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1605 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1607 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
1608 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
1610 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
1611 if (!*(BYTE
**)pvStructInfo
)
1614 *pcbStructInfo
= bytesNeeded
;
1616 else if (*pcbStructInfo
< bytesNeeded
)
1618 *pcbStructInfo
= bytesNeeded
;
1619 SetLastError(ERROR_MORE_DATA
);
1625 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_FLAG. */
1626 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1627 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, LPSTR pszObjId
,
1634 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1638 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1640 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1645 /* The largest possible string for the first two components
1646 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1651 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1652 pbEncoded
[1 + lenBytes
] / 40,
1653 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1655 bytesNeeded
= strlen(firstTwo
) + 1;
1656 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1657 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1659 /* large enough for ".4000000" */
1663 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1670 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1673 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1680 snprintf(str
, sizeof(str
), ".%d", val
);
1681 bytesNeeded
+= strlen(str
);
1685 *pcbObjId
= bytesNeeded
;
1686 else if (*pcbObjId
< bytesNeeded
)
1688 *pcbObjId
= bytesNeeded
;
1689 SetLastError(ERROR_MORE_DATA
);
1694 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1695 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1697 pszObjId
+= strlen(pszObjId
);
1698 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1699 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1703 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1712 sprintf(pszObjId
, ".%d", val
);
1713 pszObjId
+= strlen(pszObjId
);
1719 *pcbObjId
= bytesNeeded
;
1724 SetLastError(CRYPT_E_ASN1_BADTAG
);
1728 __EXCEPT(page_fault
)
1730 SetLastError(STATUS_ACCESS_VIOLATION
);
1737 /* Warning: this assumes the address of value->Value.pbData is already set, in
1738 * order to avoid overwriting memory. (In some cases, it may change it, if it
1739 * doesn't copy anything to memory.) Be sure to set it correctly!
1741 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
1742 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, CERT_NAME_VALUE
*value
,
1751 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1753 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1755 switch (pbEncoded
[0])
1757 case ASN_NUMERICSTRING
:
1758 case ASN_PRINTABLESTRING
:
1762 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
1763 SetLastError(OSS_UNIMPLEMENTED
);
1768 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
1770 switch (pbEncoded
[0])
1772 case ASN_NUMERICSTRING
:
1773 case ASN_PRINTABLESTRING
:
1775 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1776 bytesNeeded
+= dataLen
;
1780 *pcbValue
= bytesNeeded
;
1781 else if (*pcbValue
< bytesNeeded
)
1783 *pcbValue
= bytesNeeded
;
1784 SetLastError(ERROR_MORE_DATA
);
1789 *pcbValue
= bytesNeeded
;
1790 switch (pbEncoded
[0])
1792 case ASN_NUMERICSTRING
:
1793 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
1795 case ASN_PRINTABLESTRING
:
1796 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
1799 value
->dwValueType
= CERT_RDN_IA5_STRING
;
1804 switch (pbEncoded
[0])
1806 case ASN_NUMERICSTRING
:
1807 case ASN_PRINTABLESTRING
:
1809 value
->Value
.cbData
= dataLen
;
1810 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1811 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
1815 if (!value
->Value
.pbData
)
1817 SetLastError(CRYPT_E_ASN1_INTERNAL
);
1821 memcpy(value
->Value
.pbData
,
1822 pbEncoded
+ 1 + lenBytes
, dataLen
);
1829 value
->Value
.cbData
= 0;
1830 value
->Value
.pbData
= NULL
;
1836 __EXCEPT(page_fault
)
1838 SetLastError(STATUS_ACCESS_VIOLATION
);
1845 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType
,
1846 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN_ATTR
*attr
,
1853 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
1855 DWORD bytesNeeded
, dataLen
, size
;
1858 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1860 /* The data length must be at least 4, two for the tag and
1861 * length for the OID, and two for the string (assuming both
1862 * have short-form lengths.)
1866 SetLastError(CRYPT_E_ASN1_EOD
);
1871 bytesNeeded
= sizeof(CERT_RDN_ATTR
);
1872 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1873 ret
= CRYPT_AsnDecodeOid(dwCertEncodingType
, pbEncoded
+ 1
1874 + lenBytes
, cbEncoded
- 1 - lenBytes
, dwFlags
, NULL
,
1878 /* ugly: need to know the size of the next element of
1879 * the sequence, so get it directly
1881 DWORD objIdOfset
= 1 + lenBytes
, objIdLen
,
1882 nameValueOffset
= 0;
1884 ret
= CRYPT_GetLen(pbEncoded
+ objIdOfset
,
1885 cbEncoded
- objIdOfset
, &objIdLen
);
1886 bytesNeeded
+= size
;
1887 /* hack: like encoding, this takes advantage of the
1888 * fact that the rest of the structure is identical to
1889 * a CERT_NAME_VALUE.
1893 nameValueOffset
= objIdOfset
+ objIdLen
+ 1 +
1894 GET_LEN_BYTES(pbEncoded
[objIdOfset
]);
1895 ret
= CRYPT_AsnDecodeNameValue(dwCertEncodingType
,
1896 pbEncoded
+ nameValueOffset
,
1897 cbEncoded
- nameValueOffset
, dwFlags
, NULL
, &size
);
1901 bytesNeeded
+= size
;
1903 *pcbAttr
= bytesNeeded
;
1904 else if (*pcbAttr
< bytesNeeded
)
1906 *pcbAttr
= bytesNeeded
;
1907 SetLastError(ERROR_MORE_DATA
);
1912 BYTE
*originalData
= attr
->Value
.pbData
;
1914 *pcbAttr
= bytesNeeded
;
1915 /* strange: decode the value first, because it
1916 * has a counted size, and we can store the OID
1917 * after it. Keep track of the original data
1918 * pointer, we'll need to know whether it was
1922 ret
= CRYPT_AsnDecodeNameValue(
1924 pbEncoded
+ nameValueOffset
,
1925 cbEncoded
- nameValueOffset
,
1926 dwFlags
, (CERT_NAME_VALUE
*)&attr
->dwValueType
,
1932 /* if the data were copied to the
1933 * original location, the OID goes
1934 * after. Otherwise it goes in the
1935 * spot originally reserved for the
1938 if (attr
->Value
.pbData
== originalData
)
1940 (LPSTR
)(attr
->Value
.pbData
+
1941 attr
->Value
.cbData
);
1943 attr
->pszObjId
= originalData
;
1944 size
= bytesNeeded
- size
;
1945 ret
= CRYPT_AsnDecodeOid(
1947 pbEncoded
+ objIdOfset
,
1948 cbEncoded
- objIdOfset
,
1949 dwFlags
, attr
->pszObjId
, &size
);
1952 attr
->pszObjId
= NULL
;
1962 SetLastError(CRYPT_E_ASN1_BADTAG
);
1966 __EXCEPT(page_fault
)
1968 SetLastError(STATUS_ACCESS_VIOLATION
);
1975 /* FIXME: this is indenting-happy, try to break it up */
1976 static BOOL WINAPI
CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType
,
1977 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN
*rdn
,
1984 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SETOF
))
1988 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1990 DWORD bytesNeeded
, cRDNAttr
= 0;
1991 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1993 bytesNeeded
= sizeof(CERT_RDN
);
1999 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2000 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
2002 ret
= CRYPT_AsnDecodeRdnAttr(dwCertEncodingType
, ptr
,
2003 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
2009 bytesNeeded
+= size
;
2010 ret
= CRYPT_GetLen(ptr
,
2011 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2013 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2020 *pcbRdn
= bytesNeeded
;
2021 else if (*pcbRdn
< bytesNeeded
)
2023 *pcbRdn
= bytesNeeded
;
2024 SetLastError(ERROR_MORE_DATA
);
2029 *pcbRdn
= bytesNeeded
;
2030 rdn
->cRDNAttr
= cRDNAttr
;
2031 if (rdn
->cRDNAttr
== 0)
2032 rdn
->rgRDNAttr
= NULL
;
2040 (CERT_RDN_ATTR
*)((BYTE
*)rdn
+ sizeof(CERT_RDN
));
2041 nextData
= (BYTE
*)rdn
->rgRDNAttr
+
2042 rdn
->cRDNAttr
* sizeof(CERT_RDN_ATTR
);
2043 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2044 i
< cRDNAttr
&& ptr
- pbEncoded
- 1 - lenBytes
<
2047 rdn
->rgRDNAttr
[i
].Value
.pbData
= nextData
;
2049 ret
= CRYPT_AsnDecodeRdnAttr(dwCertEncodingType
,
2050 ptr
, cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
2051 &rdn
->rgRDNAttr
[i
], &size
);
2056 bytesNeeded
-= size
;
2057 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG,
2058 * the data may not have been copied.
2060 if (rdn
->rgRDNAttr
[i
].Value
.pbData
==
2063 rdn
->rgRDNAttr
[i
].Value
.cbData
;
2064 /* Ugly: the OID, if copied, is stored in
2065 * memory after the value, so increment by
2066 * its string length if it's set and points
2069 if ((const BYTE
*)rdn
->rgRDNAttr
[i
].pszObjId
2072 strlen(rdn
->rgRDNAttr
[i
].pszObjId
) + 1;
2073 ret
= CRYPT_GetLen(ptr
,
2074 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2076 ptr
+= nextLen
+ 1 +
2077 GET_LEN_BYTES(ptr
[1]);
2087 SetLastError(CRYPT_E_ASN1_BADTAG
);
2091 __EXCEPT(page_fault
)
2093 SetLastError(STATUS_ACCESS_VIOLATION
);
2100 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
2101 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2102 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2108 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCEOF
))
2112 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2114 DWORD bytesNeeded
, cRDN
= 0;
2115 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2117 bytesNeeded
= sizeof(CERT_NAME_INFO
);
2122 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2123 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
2127 ret
= CRYPT_AsnDecodeRdn(dwCertEncodingType
, ptr
,
2128 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
2134 bytesNeeded
+= size
;
2135 ret
= CRYPT_GetLen(ptr
,
2136 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2138 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2145 *pcbStructInfo
= bytesNeeded
;
2146 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2147 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2149 CERT_NAME_INFO
*info
;
2151 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2152 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2153 info
= (CERT_NAME_INFO
*)pvStructInfo
;
2155 if (info
->cRDN
== 0)
2163 info
->rgRDN
= (CERT_RDN
*)((BYTE
*)pvStructInfo
+
2164 sizeof(CERT_NAME_INFO
));
2165 nextData
= (BYTE
*)info
->rgRDN
+
2166 info
->cRDN
* sizeof(CERT_RDN
);
2167 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2168 i
< cRDN
&& ptr
- pbEncoded
- 1 - lenBytes
<
2171 info
->rgRDN
[i
].rgRDNAttr
=
2172 (CERT_RDN_ATTR
*)nextData
;
2174 ret
= CRYPT_AsnDecodeRdn(dwCertEncodingType
,
2175 ptr
, cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
2176 &info
->rgRDN
[i
], &size
);
2182 bytesNeeded
-= size
;
2183 ret
= CRYPT_GetLen(ptr
,
2184 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2186 ptr
+= nextLen
+ 1 +
2187 GET_LEN_BYTES(ptr
[1]);
2195 SetLastError(CRYPT_E_ASN1_BADTAG
);
2201 __EXCEPT(page_fault
)
2203 SetLastError(STATUS_ACCESS_VIOLATION
);
2210 static BOOL WINAPI
CRYPT_DecodeBool(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2215 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2218 if (pbEncoded
[0] != ASN_BOOL
)
2220 SetLastError(CRYPT_E_ASN1_BADTAG
);
2223 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2225 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2228 if (pbEncoded
[1] > 1)
2230 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2233 *val
= pbEncoded
[2] ? TRUE
: FALSE
;
2237 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
2238 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2239 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2245 if (pbEncoded
[0] == ASN_SEQUENCE
)
2249 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2251 /* sanity-check length, space enough for 7 bytes of integer and
2256 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2261 DWORD bytesNeeded
= sizeof(CERT_BASIC_CONSTRAINTS2_INFO
);
2264 *pcbStructInfo
= bytesNeeded
;
2268 CERT_BASIC_CONSTRAINTS2_INFO info
= { 0 };
2270 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2271 pbEncoded
+= 1 + lenBytes
;
2272 cbEncoded
-= 1 + lenBytes
;
2277 if (pbEncoded
[0] == ASN_BOOL
)
2279 ret
= CRYPT_DecodeBool(pbEncoded
, cbEncoded
,
2283 cbEncoded
-= 2 + pbEncoded
[1];
2284 pbEncoded
+= 2 + pbEncoded
[1];
2287 if (ret
&& cbEncoded
&& pbEncoded
[0] == ASN_INTEGER
)
2289 size
= sizeof(info
.dwPathLenConstraint
);
2290 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
,
2291 X509_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
,
2292 &info
.dwPathLenConstraint
, &size
);
2295 cbEncoded
-= 2 + pbEncoded
[1];
2296 pbEncoded
+= 2 + pbEncoded
[1];
2299 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2303 info
.fPathLenConstraint
= TRUE
;
2309 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2310 pDecodePara
, pvStructInfo
, pcbStructInfo
,
2313 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2314 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2315 memcpy(pvStructInfo
, &info
,
2316 sizeof(CERT_BASIC_CONSTRAINTS2_INFO
));
2325 SetLastError(CRYPT_E_ASN1_BADTAG
);
2329 __EXCEPT(page_fault
)
2331 SetLastError(STATUS_ACCESS_VIOLATION
);
2338 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
2339 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2340 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2346 if (pbEncoded
[0] == ASN_OCTETSTRING
)
2348 DWORD bytesNeeded
, dataLen
;
2350 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2352 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2353 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
2355 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
2357 *pcbStructInfo
= bytesNeeded
;
2358 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2359 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2361 CRYPT_DATA_BLOB
*blob
;
2362 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2364 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2365 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2366 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2367 blob
->cbData
= dataLen
;
2368 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2369 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
2372 blob
->pbData
= (BYTE
*)pvStructInfo
+
2373 sizeof(CRYPT_DATA_BLOB
);
2375 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
2383 SetLastError(CRYPT_E_ASN1_BADTAG
);
2387 __EXCEPT(page_fault
)
2389 SetLastError(STATUS_ACCESS_VIOLATION
);
2396 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
2397 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2398 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2404 if (pbEncoded
[0] == ASN_BITSTRING
)
2406 DWORD bytesNeeded
, dataLen
;
2408 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2410 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2411 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
2413 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
2415 *pcbStructInfo
= bytesNeeded
;
2416 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2417 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2419 CRYPT_BIT_BLOB
*blob
;
2421 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2422 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2423 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2424 blob
->cbData
= dataLen
- 1;
2425 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
2426 GET_LEN_BYTES(pbEncoded
[1]));
2427 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2428 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
2429 GET_LEN_BYTES(pbEncoded
[1]);
2432 blob
->pbData
= (BYTE
*)pvStructInfo
+
2433 sizeof(CRYPT_BIT_BLOB
);
2436 BYTE mask
= 0xff << blob
->cUnusedBits
;
2438 memcpy(blob
->pbData
, pbEncoded
+ 2 +
2439 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
2440 blob
->pbData
[blob
->cbData
- 1] &= mask
;
2448 SetLastError(CRYPT_E_ASN1_BADTAG
);
2452 __EXCEPT(page_fault
)
2454 SetLastError(STATUS_ACCESS_VIOLATION
);
2461 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2462 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2463 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2469 *pcbStructInfo
= sizeof(int);
2474 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
2475 DWORD size
= sizeof(buf
);
2477 ret
= CRYPT_AsnDecodeInteger(dwCertEncodingType
,
2478 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
2481 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
2483 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2484 pvStructInfo
, pcbStructInfo
, sizeof(int))))
2488 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2489 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2490 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
2492 /* initialize to a negative value to sign-extend */
2497 for (i
= 0; i
< blob
->cbData
; i
++)
2500 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
2502 memcpy(pvStructInfo
, &val
, sizeof(int));
2505 else if (GetLastError() == ERROR_MORE_DATA
)
2506 SetLastError(CRYPT_E_ASN1_LARGE
);
2508 __EXCEPT(page_fault
)
2510 SetLastError(STATUS_ACCESS_VIOLATION
);
2517 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
2518 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2519 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2525 if (pbEncoded
[0] == ASN_INTEGER
)
2527 DWORD bytesNeeded
, dataLen
;
2529 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2531 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2533 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2535 *pcbStructInfo
= bytesNeeded
;
2536 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2537 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2539 CRYPT_INTEGER_BLOB
*blob
;
2541 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2542 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2543 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2544 blob
->cbData
= dataLen
;
2545 blob
->pbData
= (BYTE
*)pvStructInfo
+
2546 sizeof(CRYPT_INTEGER_BLOB
);
2551 for (i
= 0; i
< blob
->cbData
; i
++)
2552 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
2560 SetLastError(CRYPT_E_ASN1_BADTAG
);
2564 __EXCEPT(page_fault
)
2566 SetLastError(STATUS_ACCESS_VIOLATION
);
2573 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
2574 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2575 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2581 if (pbEncoded
[0] == ASN_INTEGER
)
2583 DWORD bytesNeeded
, dataLen
;
2584 CRYPT_INTEGER_BLOB
*blob
;
2586 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2588 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2590 *pcbStructInfo
= bytesNeeded
;
2591 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2592 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2594 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2596 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2597 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2598 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2599 blob
->cbData
= dataLen
;
2600 blob
->pbData
= (BYTE
*)pvStructInfo
+
2601 sizeof(CRYPT_INTEGER_BLOB
);
2602 /* remove leading zero byte if it exists */
2603 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
2612 for (i
= 0; i
< blob
->cbData
; i
++)
2613 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
2614 pbEncoded
[1] - i
- 1);
2621 SetLastError(CRYPT_E_ASN1_BADTAG
);
2625 __EXCEPT(page_fault
)
2627 SetLastError(STATUS_ACCESS_VIOLATION
);
2634 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
2635 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2636 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2642 *pcbStructInfo
= sizeof(int);
2647 if (pbEncoded
[0] == ASN_ENUMERATED
)
2649 unsigned int val
= 0, i
;
2653 SetLastError(CRYPT_E_ASN1_EOD
);
2656 else if (pbEncoded
[1] == 0)
2658 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2663 /* A little strange looking, but we have to accept a sign byte:
2664 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2665 * assuming a small length is okay here, it has to be in short
2668 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
2670 SetLastError(CRYPT_E_ASN1_LARGE
);
2673 for (i
= 0; i
< pbEncoded
[1]; i
++)
2676 val
|= pbEncoded
[2 + i
];
2678 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2679 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
2681 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2682 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2683 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
2689 SetLastError(CRYPT_E_ASN1_BADTAG
);
2693 __EXCEPT(page_fault
)
2695 SetLastError(STATUS_ACCESS_VIOLATION
);
2702 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2705 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2710 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2712 if (!isdigit(*(pbEncoded))) \
2714 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2720 (word) += *(pbEncoded)++ - '0'; \
2725 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
2726 SYSTEMTIME
*sysTime
)
2732 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
2734 WORD hours
, minutes
= 0;
2735 BYTE sign
= *pbEncoded
++;
2738 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
2739 if (ret
&& hours
>= 24)
2741 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2746 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
2747 if (ret
&& minutes
>= 60)
2749 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2757 sysTime
->wHour
+= hours
;
2758 sysTime
->wMinute
+= minutes
;
2762 if (hours
> sysTime
->wHour
)
2765 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
2768 sysTime
->wHour
-= hours
;
2769 if (minutes
> sysTime
->wMinute
)
2772 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
2775 sysTime
->wMinute
-= minutes
;
2780 __EXCEPT(page_fault
)
2782 SetLastError(STATUS_ACCESS_VIOLATION
);
2789 #define MIN_ENCODED_TIME_LENGTH 10
2791 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
2792 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2793 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2799 *pcbStructInfo
= sizeof(FILETIME
);
2804 if (pbEncoded
[0] == ASN_UTCTIME
)
2808 SetLastError(CRYPT_E_ASN1_EOD
);
2811 else if (pbEncoded
[1] > 0x7f)
2813 /* long-form date strings really can't be valid */
2814 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2819 SYSTEMTIME sysTime
= { 0 };
2820 BYTE len
= pbEncoded
[1];
2822 if (len
< MIN_ENCODED_TIME_LENGTH
)
2824 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2830 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
2831 if (sysTime
.wYear
>= 50)
2832 sysTime
.wYear
+= 1900;
2834 sysTime
.wYear
+= 2000;
2835 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
2836 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
2837 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
2838 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
2841 if (len
>= 2 && isdigit(*pbEncoded
) &&
2842 isdigit(*(pbEncoded
+ 1)))
2843 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
2845 else if (isdigit(*pbEncoded
))
2846 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
2849 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
2852 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2853 pDecodePara
, pvStructInfo
, pcbStructInfo
,
2856 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2857 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2858 ret
= SystemTimeToFileTime(&sysTime
,
2859 (FILETIME
*)pvStructInfo
);
2866 SetLastError(CRYPT_E_ASN1_BADTAG
);
2870 __EXCEPT(page_fault
)
2872 SetLastError(STATUS_ACCESS_VIOLATION
);
2879 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
2880 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2881 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2887 *pcbStructInfo
= sizeof(FILETIME
);
2892 if (pbEncoded
[0] == ASN_GENERALTIME
)
2896 SetLastError(CRYPT_E_ASN1_EOD
);
2899 else if (pbEncoded
[1] > 0x7f)
2901 /* long-form date strings really can't be valid */
2902 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2907 BYTE len
= pbEncoded
[1];
2909 if (len
< MIN_ENCODED_TIME_LENGTH
)
2911 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2916 SYSTEMTIME sysTime
= { 0 };
2919 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
2920 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
2921 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
2922 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
2925 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
2928 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
2930 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
2937 /* workaround macro weirdness */
2938 digits
= min(len
, 3);
2939 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
2940 sysTime
.wMilliseconds
);
2943 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
2946 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2947 pDecodePara
, pvStructInfo
, pcbStructInfo
,
2950 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2951 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2952 ret
= SystemTimeToFileTime(&sysTime
,
2953 (FILETIME
*)pvStructInfo
);
2960 SetLastError(CRYPT_E_ASN1_BADTAG
);
2964 __EXCEPT(page_fault
)
2966 SetLastError(STATUS_ACCESS_VIOLATION
);
2973 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
2974 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2975 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2981 *pcbStructInfo
= sizeof(FILETIME
);
2987 if (pbEncoded
[0] == ASN_UTCTIME
)
2988 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
2989 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2991 else if (pbEncoded
[0] == ASN_GENERALTIME
)
2992 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
2993 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
2994 pvStructInfo
, pcbStructInfo
);
2997 SetLastError(CRYPT_E_ASN1_BADTAG
);
3001 __EXCEPT(page_fault
)
3003 SetLastError(STATUS_ACCESS_VIOLATION
);
3010 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
3011 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3012 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3018 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3020 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
3022 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3027 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3028 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
3030 ptr
= pbEncoded
+ 1 + lenBytes
;
3031 remainingLen
= dataLen
;
3032 while (ret
&& remainingLen
)
3036 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3039 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3041 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3042 ptr
+= 1 + nextLenBytes
+ nextLen
;
3043 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
3044 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3045 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
3051 CRYPT_SEQUENCE_OF_ANY
*seq
;
3055 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3056 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3058 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3059 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3060 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3061 seq
->cValue
= cValue
;
3062 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
3064 nextPtr
= (BYTE
*)seq
->rgValue
+
3065 cValue
* sizeof(CRYPT_DER_BLOB
);
3066 ptr
= pbEncoded
+ 1 + lenBytes
;
3067 remainingLen
= dataLen
;
3069 while (ret
&& remainingLen
)
3073 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3076 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3078 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
3080 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3081 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
3084 seq
->rgValue
[i
].pbData
= nextPtr
;
3085 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
3087 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
3089 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3090 ptr
+= 1 + nextLenBytes
+ nextLen
;
3100 SetLastError(CRYPT_E_ASN1_BADTAG
);
3104 __EXCEPT(page_fault
)
3106 SetLastError(STATUS_ACCESS_VIOLATION
);
3113 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
3114 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
3116 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3117 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3118 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3122 CryptDecodeObjectExFunc decodeFunc
= NULL
;
3124 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3125 dwCertEncodingType
, HIWORD(lpszStructType
) ? debugstr_a(lpszStructType
) :
3126 "(integer value)", pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
3127 pvStructInfo
, pcbStructInfo
);
3129 if (!pvStructInfo
&& !pcbStructInfo
)
3131 SetLastError(ERROR_INVALID_PARAMETER
);
3134 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3135 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3137 SetLastError(ERROR_FILE_NOT_FOUND
);
3140 if (!pbEncoded
|| !cbEncoded
)
3142 SetLastError(CRYPT_E_ASN1_EOD
);
3145 if (cbEncoded
> MAX_ENCODED_LEN
)
3147 SetLastError(CRYPT_E_ASN1_LARGE
);
3151 SetLastError(NOERROR
);
3152 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
3153 *(BYTE
**)pvStructInfo
= NULL
;
3154 if (!HIWORD(lpszStructType
))
3156 switch (LOWORD(lpszStructType
))
3158 case (WORD
)X509_NAME
:
3159 decodeFunc
= CRYPT_AsnDecodeName
;
3161 case (WORD
)X509_BASIC_CONSTRAINTS2
:
3162 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
3164 case (WORD
)X509_OCTET_STRING
:
3165 decodeFunc
= CRYPT_AsnDecodeOctets
;
3167 case (WORD
)X509_BITS
:
3168 case (WORD
)X509_KEY_USAGE
:
3169 decodeFunc
= CRYPT_AsnDecodeBits
;
3171 case (WORD
)X509_INTEGER
:
3172 decodeFunc
= CRYPT_AsnDecodeInt
;
3174 case (WORD
)X509_MULTI_BYTE_INTEGER
:
3175 decodeFunc
= CRYPT_AsnDecodeInteger
;
3177 case (WORD
)X509_MULTI_BYTE_UINT
:
3178 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
3180 case (WORD
)X509_ENUMERATED
:
3181 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
3183 case (WORD
)X509_CHOICE_OF_TIME
:
3184 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
3186 case (WORD
)X509_SEQUENCE_OF_ANY
:
3187 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
3189 case (WORD
)PKCS_UTC_TIME
:
3190 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
3193 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
3196 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
3197 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
3198 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
3199 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
3200 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
3201 decodeFunc
= CRYPT_AsnDecodeBits
;
3202 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
3203 decodeFunc
= CRYPT_AsnDecodeOctets
;
3204 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
3205 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
3207 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3208 debugstr_a(lpszStructType
));
3210 decodeFunc
= (CryptDecodeObjectExFunc
)CRYPT_GetFunc(dwCertEncodingType
,
3211 lpszStructType
, "CryptDecodeObjectEx", &lib
);
3213 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
3214 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
3216 SetLastError(ERROR_FILE_NOT_FOUND
);