2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * This file implements ASN.1 DER encoding and decoding of a limited set of
19 * types. It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
38 #define NONAMELESSUNION
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 /* a few asn.1 tags we need */
54 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
55 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
56 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
57 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
58 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
59 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
60 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
61 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
62 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
64 #define ASN_FLAGS_MASK 0xf0
65 #define ASN_TYPE_MASK 0x0f
67 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
69 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
71 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
72 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
73 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
74 DWORD
, DWORD
, void *, DWORD
*);
75 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
76 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
78 /* Prototypes for built-in encoders/decoders. They follow the Ex style
79 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
80 * built-in functions, but the parameters are retained to simplify
81 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
82 * external DLLs that follow these signatures.
83 * FIXME: some built-in functions are suitable to be called directly by
84 * CryptEncodeObjectEx/CryptDecodeObjectEx (they implement exception handling
85 * and memory allocation if requested), others are only suitable to be called
86 * internally. Comment which are which.
88 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
89 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
90 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
91 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
92 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
93 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
94 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
95 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
96 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
99 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
100 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
101 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
102 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
104 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
105 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
106 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
107 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
108 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
109 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
110 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
111 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
112 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
113 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
114 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
115 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
116 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
117 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
118 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
122 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
123 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
124 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
125 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
126 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
127 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
128 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
129 * time, doesn't do memory allocation, and doesn't do exception handling.
130 * (This isn't intended to be the externally-called one.)
132 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
133 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
134 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
135 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
136 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
);
137 /* Assumes algo->Parameters.pbData is set ahead of time */
138 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
139 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
140 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
141 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
142 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
143 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
144 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
145 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
146 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
147 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
148 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
149 * member has been initialized, doesn't do exception handling, and doesn't do
152 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
153 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
154 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
155 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
156 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
157 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
158 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
159 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
160 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
161 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
162 * member has been initialized, doesn't do exception handling, and doesn't do
165 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
166 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
167 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
168 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
169 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
170 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
171 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
172 void *pvStructInfo
, DWORD
*pcbStructInfo
);
174 /* filter for page-fault exceptions */
175 static WINE_EXCEPTION_FILTER(page_fault
)
177 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
178 return EXCEPTION_EXECUTE_HANDLER
;
179 return EXCEPTION_CONTINUE_SEARCH
;
182 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
183 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
185 static HCRYPTOIDFUNCSET set
= NULL
;
187 HCRYPTOIDFUNCADDR hFunc
;
188 CryptEncodeObjectFunc pCryptEncodeObject
;
190 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
191 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
194 if (!pbEncoded
&& !pcbEncoded
)
196 SetLastError(ERROR_INVALID_PARAMETER
);
200 /* Try registered DLL first.. */
202 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
203 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
204 (void **)&pCryptEncodeObject
, &hFunc
);
205 if (pCryptEncodeObject
)
207 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
208 pvStructInfo
, pbEncoded
, pcbEncoded
);
209 CryptFreeOIDFunctionAddress(hFunc
, 0);
213 /* If not, use CryptEncodeObjectEx */
214 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
215 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
220 /* Helper function to check *pcbEncoded, set it to the required size, and
221 * optionally to allocate memory. Assumes pbEncoded is not NULL.
222 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
223 * pointer to the newly allocated memory.
225 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
226 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
231 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
233 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
234 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
236 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
237 if (!*(BYTE
**)pbEncoded
)
240 *pcbEncoded
= bytesNeeded
;
242 else if (bytesNeeded
> *pcbEncoded
)
244 *pcbEncoded
= bytesNeeded
;
245 SetLastError(ERROR_MORE_DATA
);
251 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
253 DWORD bytesNeeded
, significantBytes
= 0;
261 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
262 temp
<<= 8, significantBytes
--)
264 bytesNeeded
= significantBytes
+ 1;
268 *pcbEncoded
= bytesNeeded
;
271 if (*pcbEncoded
< bytesNeeded
)
273 SetLastError(ERROR_MORE_DATA
);
277 *pbEncoded
= (BYTE
)len
;
282 *pbEncoded
++ = significantBytes
| 0x80;
283 for (i
= 0; i
< significantBytes
; i
++)
285 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
289 *pcbEncoded
= bytesNeeded
;
293 struct AsnEncodeSequenceItem
295 const void *pvStructInfo
;
296 CryptEncodeObjectExFunc encodeFunc
;
297 DWORD size
; /* used during encoding, not for your use */
300 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
301 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
302 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
305 DWORD i
, dataLen
= 0;
307 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
308 pbEncoded
, *pcbEncoded
);
309 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
311 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
312 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
313 NULL
, &items
[i
].size
);
314 dataLen
+= items
[i
].size
;
318 DWORD lenBytes
, bytesNeeded
;
320 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
321 bytesNeeded
= 1 + lenBytes
+ dataLen
;
323 *pcbEncoded
= bytesNeeded
;
326 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
327 pcbEncoded
, bytesNeeded
)))
329 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
330 pbEncoded
= *(BYTE
**)pbEncoded
;
331 *pbEncoded
++ = ASN_SEQUENCE
;
332 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
333 pbEncoded
+= lenBytes
;
334 for (i
= 0; ret
&& i
< cItem
; i
++)
336 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
337 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
338 NULL
, pbEncoded
, &items
[i
].size
);
339 pbEncoded
+= items
[i
].size
;
344 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
348 struct AsnConstructedItem
351 const void *pvStructInfo
;
352 CryptEncodeObjectExFunc encodeFunc
;
355 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
356 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
357 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
360 const struct AsnConstructedItem
*item
=
361 (const struct AsnConstructedItem
*)pvStructInfo
;
364 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
365 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
367 DWORD dataLen
, bytesNeeded
;
369 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
370 bytesNeeded
= 1 + dataLen
+ len
;
372 *pcbEncoded
= bytesNeeded
;
373 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
374 pbEncoded
, pcbEncoded
, bytesNeeded
)))
376 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
377 pbEncoded
= *(BYTE
**)pbEncoded
;
378 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
379 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
380 pbEncoded
+= dataLen
;
381 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
382 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
389 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
390 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
391 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
393 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
396 /* CERT_V1 is not encoded */
404 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
406 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
407 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
412 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
413 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
414 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
416 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
421 *pcbEncoded
= blob
->cbData
;
424 else if (*pcbEncoded
< blob
->cbData
)
426 *pcbEncoded
= blob
->cbData
;
427 SetLastError(ERROR_MORE_DATA
);
433 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
434 *pcbEncoded
= blob
->cbData
;
440 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
441 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
442 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
445 /* This has two filetimes in a row, a NotBefore and a NotAfter */
446 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
447 struct AsnEncodeSequenceItem items
[] = {
448 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
449 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
452 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
453 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
458 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
459 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
460 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
463 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
464 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
466 struct AsnEncodeSequenceItem items
[] = {
467 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
468 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
471 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
472 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
477 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
478 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
479 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
485 const CERT_PUBLIC_KEY_INFO
*info
=
486 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
487 struct AsnEncodeSequenceItem items
[] = {
488 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
489 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
492 TRACE("Encoding public key with OID %s\n",
493 debugstr_a(info
->Algorithm
.pszObjId
));
494 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
495 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
500 SetLastError(STATUS_ACCESS_VIOLATION
);
507 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
508 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
509 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
515 const CERT_SIGNED_CONTENT_INFO
*info
=
516 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
517 struct AsnEncodeSequenceItem items
[] = {
518 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
519 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
520 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
523 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
524 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
525 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
526 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
531 SetLastError(STATUS_ACCESS_VIOLATION
);
538 /* Like in Windows, this blithely ignores the validity of the passed-in
539 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
540 * decode properly, see CRYPT_AsnDecodeCertInfo.
542 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
543 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
544 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
550 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
551 struct AsnEncodeSequenceItem items
[10] = {
552 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
553 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
554 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
555 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
556 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
557 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
558 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
561 struct AsnConstructedItem constructed
[3] = { { 0 } };
562 DWORD cItem
= 7, cConstructed
= 0;
564 if (info
->IssuerUniqueId
.cbData
)
566 constructed
[cConstructed
].tag
= 1;
567 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
568 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
569 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
570 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
574 if (info
->SubjectUniqueId
.cbData
)
576 constructed
[cConstructed
].tag
= 2;
577 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
578 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
579 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
580 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
584 if (info
->cExtension
)
586 constructed
[cConstructed
].tag
= 3;
587 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
588 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
589 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
590 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
595 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
596 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
600 SetLastError(STATUS_ACCESS_VIOLATION
);
607 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
608 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
610 struct AsnEncodeSequenceItem items
[3] = {
611 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
612 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
618 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
620 if (entry
->cExtension
)
622 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
623 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
627 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
628 pbEncoded
, pcbEncoded
);
630 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
634 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
635 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
636 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
638 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
639 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
640 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
641 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
644 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
648 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
652 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
653 bytesNeeded
= 1 + lenBytes
+ dataLen
;
655 *pcbEncoded
= bytesNeeded
;
658 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
659 pcbEncoded
, bytesNeeded
)))
661 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
662 pbEncoded
= *(BYTE
**)pbEncoded
;
663 *pbEncoded
++ = ASN_SEQUENCEOF
;
664 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
665 pbEncoded
+= lenBytes
;
666 for (i
= 0; i
< cCRLEntry
; i
++)
668 DWORD size
= dataLen
;
670 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
679 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
680 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
681 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
683 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
686 /* CRL_V1 is not encoded */
693 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
694 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
698 /* Like in Windows, this blithely ignores the validity of the passed-in
699 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
700 * decode properly, see CRYPT_AsnDecodeCRLInfo.
702 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
703 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
704 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
710 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
711 struct AsnEncodeSequenceItem items
[7] = {
712 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
713 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
714 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
715 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
720 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
722 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
723 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
728 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
729 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
732 if (info
->cExtension
)
734 items
[cItem
].pvStructInfo
= &info
->cExtension
;
735 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
739 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
740 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
744 SetLastError(STATUS_ACCESS_VIOLATION
);
751 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
755 struct AsnEncodeSequenceItem items
[3] = {
756 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
762 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
766 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
767 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
770 items
[cItem
].pvStructInfo
= &ext
->Value
;
771 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
774 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
775 pbEncoded
, pcbEncoded
);
776 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
780 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
781 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
782 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
788 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
789 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
792 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
796 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
800 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
801 bytesNeeded
= 1 + lenBytes
+ dataLen
;
803 *pcbEncoded
= bytesNeeded
;
806 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
807 pcbEncoded
, bytesNeeded
)))
809 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
810 pbEncoded
= *(BYTE
**)pbEncoded
;
811 *pbEncoded
++ = ASN_SEQUENCEOF
;
812 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
813 pbEncoded
+= lenBytes
;
814 for (i
= 0; i
< exts
->cExtension
; i
++)
816 DWORD size
= dataLen
;
818 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
828 SetLastError(STATUS_ACCESS_VIOLATION
);
835 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
836 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
837 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
839 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
840 DWORD bytesNeeded
= 0, lenBytes
;
845 TRACE("%s\n", debugstr_a(pszObjId
));
852 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
854 SetLastError(CRYPT_E_ASN1_ERROR
);
858 firstByte
= val1
* 40 + val2
;
859 ptr
= pszObjId
+ firstPos
;
864 /* note I assume each component is at most 32-bits long in base 2 */
865 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
867 if (val1
>= 0x10000000)
869 else if (val1
>= 0x200000)
871 else if (val1
>= 0x4000)
873 else if (val1
>= 0x80)
883 SetLastError(CRYPT_E_ASN1_ERROR
);
887 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
891 bytesNeeded
+= 1 + lenBytes
;
894 if (*pcbEncoded
< bytesNeeded
)
896 SetLastError(ERROR_MORE_DATA
);
901 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
902 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
903 pbEncoded
+= lenBytes
;
909 *pbEncoded
++ = firstByte
;
910 ptr
= pszObjId
+ firstPos
;
913 sscanf(ptr
, "%d%n", &val
, &pos
);
915 unsigned char outBytes
[5];
918 if (val
>= 0x10000000)
920 else if (val
>= 0x200000)
922 else if (val
>= 0x4000)
924 else if (val
>= 0x80)
928 for (i
= numBytes
; i
> 0; i
--)
930 outBytes
[i
- 1] = val
& 0x7f;
933 for (i
= 0; i
< numBytes
- 1; i
++)
934 *pbEncoded
++ = outBytes
[i
] | 0x80;
935 *pbEncoded
++ = outBytes
[i
];
944 *pcbEncoded
= bytesNeeded
;
948 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
949 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
952 DWORD bytesNeeded
, lenBytes
, encodedLen
;
955 switch (value
->dwValueType
)
957 case CERT_RDN_NUMERIC_STRING
:
958 tag
= ASN_NUMERICSTRING
;
959 encodedLen
= value
->Value
.cbData
;
961 case CERT_RDN_PRINTABLE_STRING
:
962 tag
= ASN_PRINTABLESTRING
;
963 encodedLen
= value
->Value
.cbData
;
965 case CERT_RDN_IA5_STRING
:
967 encodedLen
= value
->Value
.cbData
;
969 case CERT_RDN_ANY_TYPE
:
970 /* explicitly disallowed */
971 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
974 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
977 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
978 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
981 if (*pcbEncoded
< bytesNeeded
)
983 SetLastError(ERROR_MORE_DATA
);
989 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
990 pbEncoded
+= lenBytes
;
991 switch (value
->dwValueType
)
993 case CERT_RDN_NUMERIC_STRING
:
994 case CERT_RDN_PRINTABLE_STRING
:
995 case CERT_RDN_IA5_STRING
:
996 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1000 *pcbEncoded
= bytesNeeded
;
1004 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1005 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1007 DWORD bytesNeeded
= 0, lenBytes
, size
;
1010 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1011 0, NULL
, NULL
, &size
);
1014 bytesNeeded
+= size
;
1015 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1016 * with dwValueType, so "cast" it to get its encoded size
1018 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1019 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1022 bytesNeeded
+= size
;
1023 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1024 bytesNeeded
+= 1 + lenBytes
;
1027 if (*pcbEncoded
< bytesNeeded
)
1029 SetLastError(ERROR_MORE_DATA
);
1034 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SEQUENCE
;
1035 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1037 pbEncoded
+= lenBytes
;
1038 size
= bytesNeeded
- 1 - lenBytes
;
1039 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1040 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1044 size
= bytesNeeded
- 1 - lenBytes
- size
;
1045 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1046 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1051 *pcbEncoded
= bytesNeeded
;
1057 static int BLOBComp(const void *l
, const void *r
)
1059 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1062 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1063 ret
= a
->cbData
- b
->cbData
;
1067 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1069 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1070 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1073 CRYPT_DER_BLOB
*blobs
= NULL
;
1077 DWORD bytesNeeded
= 0, lenBytes
, i
;
1083 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1087 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1089 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1091 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1092 NULL
, &blobs
[i
].cbData
);
1094 bytesNeeded
+= blobs
[i
].cbData
;
1098 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1099 bytesNeeded
+= 1 + lenBytes
;
1102 if (*pcbEncoded
< bytesNeeded
)
1104 SetLastError(ERROR_MORE_DATA
);
1109 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1111 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1112 if (!blobs
[i
].pbData
)
1115 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1116 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1121 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1123 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1124 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1126 pbEncoded
+= lenBytes
;
1127 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1129 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1130 pbEncoded
+= blobs
[i
].cbData
;
1135 *pcbEncoded
= bytesNeeded
;
1139 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1140 CryptMemFree(blobs
[i
].pbData
);
1143 __EXCEPT(page_fault
)
1145 SetLastError(STATUS_ACCESS_VIOLATION
);
1149 CryptMemFree(blobs
);
1153 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1154 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1155 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1161 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1162 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1164 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1166 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1168 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1171 bytesNeeded
+= size
;
1173 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1174 bytesNeeded
+= 1 + lenBytes
;
1178 *pcbEncoded
= bytesNeeded
;
1181 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1182 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1184 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1185 pbEncoded
= *(BYTE
**)pbEncoded
;
1186 *pbEncoded
++ = ASN_SEQUENCEOF
;
1187 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1189 pbEncoded
+= lenBytes
;
1190 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1193 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1194 &info
->rgRDN
[i
], pbEncoded
, &size
);
1198 bytesNeeded
-= size
;
1205 __EXCEPT(page_fault
)
1207 SetLastError(STATUS_ACCESS_VIOLATION
);
1214 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1215 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1216 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1218 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1227 else if (*pcbEncoded
< 3)
1230 SetLastError(ERROR_MORE_DATA
);
1236 *pbEncoded
++ = ASN_BOOL
;
1238 *pbEncoded
++ = val
? 0xff : 0;
1241 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1245 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1246 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1252 switch (entry
->dwAltNameChoice
)
1254 case CERT_ALT_NAME_RFC822_NAME
:
1255 case CERT_ALT_NAME_DNS_NAME
:
1256 case CERT_ALT_NAME_URL
:
1257 if (entry
->u
.pwszURL
)
1261 /* Not + 1: don't encode the NULL-terminator */
1262 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1263 for (i
= 0; ret
&& i
< dataLen
; i
++)
1265 if (entry
->u
.pwszURL
[i
] > 0x7f)
1267 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1276 case CERT_ALT_NAME_IP_ADDRESS
:
1277 dataLen
= entry
->u
.IPAddress
.cbData
;
1279 case CERT_ALT_NAME_REGISTERED_ID
:
1280 /* FIXME: encode OID */
1281 case CERT_ALT_NAME_OTHER_NAME
:
1282 case CERT_ALT_NAME_DIRECTORY_NAME
:
1283 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1286 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1291 DWORD bytesNeeded
, lenBytes
;
1293 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1294 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1296 *pcbEncoded
= bytesNeeded
;
1297 else if (*pcbEncoded
< bytesNeeded
)
1299 SetLastError(ERROR_MORE_DATA
);
1300 *pcbEncoded
= bytesNeeded
;
1305 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1306 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1307 pbEncoded
+= lenBytes
;
1308 switch (entry
->dwAltNameChoice
)
1310 case CERT_ALT_NAME_RFC822_NAME
:
1311 case CERT_ALT_NAME_DNS_NAME
:
1312 case CERT_ALT_NAME_URL
:
1316 for (i
= 0; i
< dataLen
; i
++)
1317 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1320 case CERT_ALT_NAME_IP_ADDRESS
:
1321 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1325 *pcbEncoded
= bytesNeeded
;
1328 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1332 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1333 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1334 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1340 const CERT_ALT_NAME_INFO
*info
=
1341 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1343 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1346 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1347 * can't encode an erroneous entry index if it's bigger than this.
1349 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1353 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1357 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1359 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1360 * the bad character, now set the index of the bad
1363 *pcbEncoded
= (BYTE
)i
<<
1364 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1369 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1370 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1373 *pcbEncoded
= bytesNeeded
;
1378 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1379 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1381 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1382 pbEncoded
= *(BYTE
**)pbEncoded
;
1383 *pbEncoded
++ = ASN_SEQUENCEOF
;
1384 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1385 pbEncoded
+= lenBytes
;
1386 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1388 DWORD len
= dataLen
;
1390 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1402 __EXCEPT(page_fault
)
1404 SetLastError(STATUS_ACCESS_VIOLATION
);
1411 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1412 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1413 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1419 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1420 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1421 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1426 items
[cItem
].pvStructInfo
= &info
->fCA
;
1427 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1430 if (info
->fPathLenConstraint
)
1432 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1433 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1436 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1437 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1439 __EXCEPT(page_fault
)
1441 SetLastError(STATUS_ACCESS_VIOLATION
);
1448 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1449 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1450 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1456 const BLOBHEADER
*hdr
=
1457 (const BLOBHEADER
*)pvStructInfo
;
1459 if (hdr
->bType
!= PUBLICKEYBLOB
)
1461 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1466 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1467 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1468 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1469 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1470 struct AsnEncodeSequenceItem items
[] = {
1471 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1472 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1475 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1476 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1480 __EXCEPT(page_fault
)
1482 SetLastError(STATUS_ACCESS_VIOLATION
);
1489 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1490 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1491 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1497 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1498 DWORD bytesNeeded
, lenBytes
;
1500 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1501 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1503 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1504 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1507 *pcbEncoded
= bytesNeeded
;
1512 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1513 pcbEncoded
, bytesNeeded
)))
1515 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1516 pbEncoded
= *(BYTE
**)pbEncoded
;
1517 *pbEncoded
++ = ASN_OCTETSTRING
;
1518 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1519 pbEncoded
+= lenBytes
;
1521 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1525 __EXCEPT(page_fault
)
1527 SetLastError(STATUS_ACCESS_VIOLATION
);
1531 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1535 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1536 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1537 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1543 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1544 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1547 /* yep, MS allows cUnusedBits to be >= 8 */
1548 if (!blob
->cUnusedBits
)
1550 dataBytes
= blob
->cbData
;
1553 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1555 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1556 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1564 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1565 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1568 *pcbEncoded
= bytesNeeded
;
1573 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1574 pcbEncoded
, bytesNeeded
)))
1576 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1577 pbEncoded
= *(BYTE
**)pbEncoded
;
1578 *pbEncoded
++ = ASN_BITSTRING
;
1579 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1580 pbEncoded
+= lenBytes
;
1581 *pbEncoded
++ = unusedBits
;
1584 BYTE mask
= 0xff << unusedBits
;
1588 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1589 pbEncoded
+= dataBytes
- 1;
1591 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1596 __EXCEPT(page_fault
)
1598 SetLastError(STATUS_ACCESS_VIOLATION
);
1605 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1606 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1607 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1613 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1614 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1619 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
1624 for (i
= 0; i
< newBlob
.cbData
; i
++)
1625 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1631 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1632 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1633 CryptMemFree(newBlob
.pbData
);
1635 __EXCEPT(page_fault
)
1637 SetLastError(STATUS_ACCESS_VIOLATION
);
1644 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1645 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1646 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1648 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1650 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1651 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1654 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1655 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1656 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1662 DWORD significantBytes
, lenBytes
;
1663 BYTE padByte
= 0, bytesNeeded
;
1665 const CRYPT_INTEGER_BLOB
*blob
=
1666 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1668 significantBytes
= blob
->cbData
;
1669 if (significantBytes
)
1671 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1673 /* negative, lop off leading (little-endian) 0xffs */
1674 for (; significantBytes
> 0 &&
1675 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1677 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1685 /* positive, lop off leading (little-endian) zeroes */
1686 for (; significantBytes
> 0 &&
1687 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1689 if (significantBytes
== 0)
1690 significantBytes
= 1;
1691 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1699 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1701 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1702 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1707 *pcbEncoded
= bytesNeeded
;
1712 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1713 pcbEncoded
, bytesNeeded
)))
1715 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1716 pbEncoded
= *(BYTE
**)pbEncoded
;
1717 *pbEncoded
++ = ASN_INTEGER
;
1720 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1721 pbEncoded
+= lenBytes
;
1722 *pbEncoded
++ = padByte
;
1726 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1727 pbEncoded
+= lenBytes
;
1729 for (; significantBytes
> 0; significantBytes
--)
1730 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1734 __EXCEPT(page_fault
)
1736 SetLastError(STATUS_ACCESS_VIOLATION
);
1743 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1744 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1745 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1751 DWORD significantBytes
, lenBytes
;
1754 const CRYPT_INTEGER_BLOB
*blob
=
1755 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1757 significantBytes
= blob
->cbData
;
1758 if (significantBytes
)
1760 /* positive, lop off leading (little-endian) zeroes */
1761 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
1764 if (significantBytes
== 0)
1765 significantBytes
= 1;
1766 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1770 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1772 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1773 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1778 *pcbEncoded
= bytesNeeded
;
1783 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1784 pcbEncoded
, bytesNeeded
)))
1786 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1787 pbEncoded
= *(BYTE
**)pbEncoded
;
1788 *pbEncoded
++ = ASN_INTEGER
;
1791 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1792 pbEncoded
+= lenBytes
;
1797 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1798 pbEncoded
+= lenBytes
;
1800 for (; significantBytes
> 0; significantBytes
--)
1801 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1805 __EXCEPT(page_fault
)
1807 SetLastError(STATUS_ACCESS_VIOLATION
);
1814 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
1815 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1816 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1818 CRYPT_INTEGER_BLOB blob
;
1821 /* Encode as an unsigned integer, then change the tag to enumerated */
1822 blob
.cbData
= sizeof(DWORD
);
1823 blob
.pbData
= (BYTE
*)pvStructInfo
;
1824 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
1825 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1826 if (ret
&& pbEncoded
)
1828 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1829 pbEncoded
= *(BYTE
**)pbEncoded
;
1830 pbEncoded
[0] = ASN_ENUMERATED
;
1835 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
1836 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1837 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1844 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1845 * temporary buffer because the output buffer is not NULL-terminated.
1848 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1852 *pcbEncoded
= bytesNeeded
;
1857 /* Sanity check the year, this is a two-digit year format */
1858 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1860 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
1862 SetLastError(CRYPT_E_BAD_ENCODE
);
1867 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1868 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1870 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1871 pbEncoded
= *(BYTE
**)pbEncoded
;
1872 buf
[0] = ASN_UTCTIME
;
1873 buf
[1] = bytesNeeded
- 2;
1874 snprintf(buf
+ 2, sizeof(buf
) - 2,
1875 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
1876 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
1877 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
1878 sysTime
.wMinute
, sysTime
.wSecond
);
1879 memcpy(pbEncoded
, buf
, bytesNeeded
);
1884 __EXCEPT(page_fault
)
1886 SetLastError(STATUS_ACCESS_VIOLATION
);
1893 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
1894 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1895 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1902 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1903 * temporary buffer because the output buffer is not NULL-terminated.
1906 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1910 *pcbEncoded
= bytesNeeded
;
1915 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1918 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1919 pcbEncoded
, bytesNeeded
);
1922 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1923 pbEncoded
= *(BYTE
**)pbEncoded
;
1924 buf
[0] = ASN_GENERALTIME
;
1925 buf
[1] = bytesNeeded
- 2;
1926 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
1927 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
1928 sysTime
.wMinute
, sysTime
.wSecond
);
1929 memcpy(pbEncoded
, buf
, bytesNeeded
);
1933 __EXCEPT(page_fault
)
1935 SetLastError(STATUS_ACCESS_VIOLATION
);
1942 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
1943 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1944 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1952 /* Check the year, if it's in the UTCTime range call that encode func */
1953 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
1955 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
1956 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
1957 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1959 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
1960 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
1963 __EXCEPT(page_fault
)
1965 SetLastError(STATUS_ACCESS_VIOLATION
);
1972 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
1973 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1974 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1980 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1981 const CRYPT_SEQUENCE_OF_ANY
*seq
=
1982 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
1984 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
1985 dataLen
+= seq
->rgValue
[i
].cbData
;
1986 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1987 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1990 *pcbEncoded
= bytesNeeded
;
1995 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1996 pcbEncoded
, bytesNeeded
)))
1998 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1999 pbEncoded
= *(BYTE
**)pbEncoded
;
2000 *pbEncoded
++ = ASN_SEQUENCEOF
;
2001 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2002 pbEncoded
+= lenBytes
;
2003 for (i
= 0; i
< seq
->cValue
; i
++)
2005 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2006 seq
->rgValue
[i
].cbData
);
2007 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2012 __EXCEPT(page_fault
)
2014 SetLastError(STATUS_ACCESS_VIOLATION
);
2021 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2022 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2023 void *pvEncoded
, DWORD
*pcbEncoded
)
2025 static HCRYPTOIDFUNCSET set
= NULL
;
2027 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2028 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2030 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2031 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2032 pvEncoded
, pcbEncoded
);
2034 if (!pvEncoded
&& !pcbEncoded
)
2036 SetLastError(ERROR_INVALID_PARAMETER
);
2039 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2040 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2042 SetLastError(ERROR_FILE_NOT_FOUND
);
2046 SetLastError(NOERROR
);
2047 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2048 *(BYTE
**)pvEncoded
= NULL
;
2049 if (!HIWORD(lpszStructType
))
2051 switch (LOWORD(lpszStructType
))
2053 case (WORD
)X509_CERT
:
2054 encodeFunc
= CRYPT_AsnEncodeCert
;
2056 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2057 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2059 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2060 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2062 case (WORD
)X509_EXTENSIONS
:
2063 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2065 case (WORD
)X509_NAME
:
2066 encodeFunc
= CRYPT_AsnEncodeName
;
2068 case (WORD
)X509_PUBLIC_KEY_INFO
:
2069 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2071 case (WORD
)X509_ALTERNATE_NAME
:
2072 encodeFunc
= CRYPT_AsnEncodeAltName
;
2074 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2075 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2077 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2078 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2080 case (WORD
)X509_OCTET_STRING
:
2081 encodeFunc
= CRYPT_AsnEncodeOctets
;
2083 case (WORD
)X509_BITS
:
2084 case (WORD
)X509_KEY_USAGE
:
2085 encodeFunc
= CRYPT_AsnEncodeBits
;
2087 case (WORD
)X509_INTEGER
:
2088 encodeFunc
= CRYPT_AsnEncodeInt
;
2090 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2091 encodeFunc
= CRYPT_AsnEncodeInteger
;
2093 case (WORD
)X509_MULTI_BYTE_UINT
:
2094 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2096 case (WORD
)X509_ENUMERATED
:
2097 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2099 case (WORD
)X509_CHOICE_OF_TIME
:
2100 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2102 case (WORD
)X509_SEQUENCE_OF_ANY
:
2103 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2105 case (WORD
)PKCS_UTC_TIME
:
2106 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2109 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2112 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2113 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2114 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2115 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2116 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2117 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2118 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2119 encodeFunc
= CRYPT_AsnEncodeBits
;
2120 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2121 encodeFunc
= CRYPT_AsnEncodeOctets
;
2122 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2123 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2124 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2125 encodeFunc
= CRYPT_AsnEncodeAltName
;
2126 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2127 encodeFunc
= CRYPT_AsnEncodeAltName
;
2128 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2129 encodeFunc
= CRYPT_AsnEncodeAltName
;
2130 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2131 encodeFunc
= CRYPT_AsnEncodeAltName
;
2132 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2133 encodeFunc
= CRYPT_AsnEncodeAltName
;
2135 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2136 debugstr_a(lpszStructType
));
2140 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
2141 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2142 (void **)&encodeFunc
, &hFunc
);
2145 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2146 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2148 SetLastError(ERROR_FILE_NOT_FOUND
);
2150 CryptFreeOIDFunctionAddress(hFunc
, 0);
2154 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2155 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2156 DWORD
*pcbStructInfo
)
2158 static HCRYPTOIDFUNCSET set
= NULL
;
2160 CryptDecodeObjectFunc pCryptDecodeObject
;
2161 HCRYPTOIDFUNCADDR hFunc
;
2163 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2164 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2165 pvStructInfo
, pcbStructInfo
);
2167 if (!pvStructInfo
&& !pcbStructInfo
)
2169 SetLastError(ERROR_INVALID_PARAMETER
);
2173 /* Try registered DLL first.. */
2175 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
2176 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2177 (void **)&pCryptDecodeObject
, &hFunc
);
2178 if (pCryptDecodeObject
)
2180 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2181 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2182 CryptFreeOIDFunctionAddress(hFunc
, 0);
2186 /* If not, use CryptDecodeObjectEx */
2187 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2188 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2193 /* Gets the number of length bytes from the given (leading) length byte */
2194 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2196 /* Helper function to get the encoded length of the data starting at pbEncoded,
2197 * where pbEncoded[0] is the tag. If the data are too short to contain a
2198 * length or if the length is too large for cbEncoded, sets an appropriate
2199 * error code and returns FALSE.
2201 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2208 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2211 else if (pbEncoded
[1] <= 0x7f)
2213 if (pbEncoded
[1] + 1 > cbEncoded
)
2215 SetLastError(CRYPT_E_ASN1_EOD
);
2220 *len
= pbEncoded
[1];
2226 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2228 if (lenLen
> sizeof(DWORD
) + 1)
2230 SetLastError(CRYPT_E_ASN1_LARGE
);
2233 else if (lenLen
+ 2 > cbEncoded
)
2235 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2246 out
|= *pbEncoded
++;
2248 if (out
+ lenLen
+ 1 > cbEncoded
)
2250 SetLastError(CRYPT_E_ASN1_EOD
);
2263 /* Helper function to check *pcbStructInfo, set it to the required size, and
2264 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2265 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2266 * pointer to the newly allocated memory.
2268 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2269 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2274 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2276 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2277 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2279 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2280 if (!*(BYTE
**)pvStructInfo
)
2283 *pcbStructInfo
= bytesNeeded
;
2285 else if (*pcbStructInfo
< bytesNeeded
)
2287 *pcbStructInfo
= bytesNeeded
;
2288 SetLastError(ERROR_MORE_DATA
);
2294 /* A few of the members need explanation:
2296 * A sequence is decoded into a struct. The offset member is the
2297 * offset of this item within that struct.
2299 * The decoder function to use. If this is NULL, then the member isn't
2300 * decoded, but minSize space is reserved for it.
2302 * The minimum amount of space occupied after decoding. You must set this.
2304 * If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then
2305 * minSize space is filled with 0 for this member. (Any other failure
2306 * results in CRYPT_AsnDecodeSequence failing.)
2307 * hasPointer, pointerOffset, minSize:
2308 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2309 * the offset within the (outer) struct of the data pointer (or to the
2310 * first data pointer, if more than one exist).
2312 * Used by CRYPT_AsnDecodeSequence, not for your use.
2314 struct AsnDecodeSequenceItem
2317 CryptDecodeObjectExFunc decodeFunc
;
2321 DWORD pointerOffset
;
2325 /* This decodes an arbitrary sequence into a contiguous block of memory
2326 * (basically, a struct.) Each element being decoded is described by a struct
2327 * AsnDecodeSequenceItem, see above.
2328 * startingPointer is an optional pointer to the first place where dynamic
2329 * data will be stored. If you know the starting offset, you may pass it
2330 * here. Otherwise, pass NULL, and one will be inferred from the items.
2331 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2332 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2334 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2335 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2336 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2337 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2341 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
2342 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2345 if (pbEncoded
[0] == ASN_SEQUENCE
)
2349 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2351 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2352 DWORD i
, bytesNeeded
= 0, minSize
= 0;
2355 ptr
= pbEncoded
+ 1 + lenBytes
;
2356 for (i
= 0; ret
&& i
< cItem
; i
++)
2360 minSize
+= items
[i
].minSize
;
2361 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2363 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2366 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2368 if (items
[i
].decodeFunc
)
2370 TRACE("sizing item %ld\n", i
);
2371 ret
= items
[i
].decodeFunc(dwCertEncodingType
, NULL
,
2372 ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2373 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2377 /* Account for alignment padding */
2378 bytesNeeded
+= items
[i
].size
;
2379 if (items
[i
].size
% sizeof(DWORD
))
2380 bytesNeeded
+= sizeof(DWORD
) -
2381 items
[i
].size
% sizeof(DWORD
);
2382 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2384 else if (items
[i
].optional
&&
2385 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2387 TRACE("skipping optional item %ld\n", i
);
2388 bytesNeeded
+= items
[i
].minSize
;
2389 SetLastError(NOERROR
);
2393 TRACE("item %ld failed: %08lx\n", i
,
2397 bytesNeeded
+= items
[i
].minSize
;
2400 else if (items
[i
].optional
)
2401 bytesNeeded
+= items
[i
].minSize
;
2404 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2408 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2410 TRACE("%ld remaining bytes, failing\n", cbEncoded
-
2412 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2418 *pcbStructInfo
= bytesNeeded
;
2419 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2420 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2424 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2425 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2426 if (startingPointer
)
2427 nextData
= (BYTE
*)startingPointer
;
2429 nextData
= (BYTE
*)pvStructInfo
+ minSize
;
2430 memset(pvStructInfo
, 0, minSize
);
2431 ptr
= pbEncoded
+ 1 + lenBytes
;
2432 for (i
= 0; ret
&& i
< cItem
; i
++)
2434 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2437 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2439 CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2441 if (items
[i
].hasPointer
)
2443 *(BYTE
**)((BYTE
*)pvStructInfo
+
2444 items
[i
].pointerOffset
) = nextData
;
2446 if (items
[i
].decodeFunc
)
2448 TRACE("decoding item %ld\n", i
);
2449 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2450 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2451 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2452 (BYTE
*)pvStructInfo
+ items
[i
].offset
,
2455 TRACE("item %ld failed: %08lx\n", i
,
2459 items
[i
].size
= items
[i
].minSize
;
2462 if (items
[i
].hasPointer
&&
2463 items
[i
].size
> items
[i
].minSize
)
2465 nextData
+= items
[i
].size
-
2467 /* align nextData to DWORD boundaries */
2468 if (items
[i
].size
% sizeof(DWORD
))
2470 nextData
+= sizeof(DWORD
) -
2471 items
[i
].size
% sizeof(DWORD
);
2474 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2476 else if (items
[i
].optional
&&
2477 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2479 SetLastError(NOERROR
);
2483 else if (!items
[i
].optional
)
2485 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2495 SetLastError(CRYPT_E_ASN1_BADTAG
);
2498 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2502 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2503 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2504 * to CRYPT_E_ASN1_CORRUPT.
2505 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2508 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2509 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2510 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2515 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2517 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2518 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2520 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2521 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2524 *pcbStructInfo
= bytesNeeded
;
2525 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2526 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2528 CRYPT_DER_BLOB
*blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
2530 blob
->cbData
= 1 + lenBytes
+ dataLen
;
2533 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2534 blob
->pbData
= (BYTE
*)pbEncoded
;
2537 assert(blob
->pbData
);
2538 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
2543 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2551 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
2552 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
2553 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2554 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2558 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
2559 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2561 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2564 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
2565 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
2566 pvStructInfo
, pcbStructInfo
);
2567 if (ret
&& pvStructInfo
)
2569 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2576 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2578 temp
= blob
->pbData
[i
];
2579 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2580 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2584 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2588 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
2589 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2590 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2594 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2595 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2599 struct AsnDecodeSequenceItem items
[] = {
2600 { offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
2601 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2602 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
2603 { offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
),
2604 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2605 FALSE
, TRUE
, offsetof(CERT_SIGNED_CONTENT_INFO
,
2606 SignatureAlgorithm
.pszObjId
), 0 },
2607 { offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
2608 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2609 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
2612 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
2613 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
2614 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2615 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2616 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2618 __EXCEPT(page_fault
)
2620 SetLastError(STATUS_ACCESS_VIOLATION
);
2627 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
2628 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2629 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2633 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
))
2637 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2639 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2641 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2642 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
2643 pvStructInfo
, pcbStructInfo
);
2648 SetLastError(CRYPT_E_ASN1_BADTAG
);
2654 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
2655 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2656 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2660 struct AsnDecodeSequenceItem items
[] = {
2661 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
2662 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2663 { offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
2664 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2667 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2668 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2669 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2673 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
2674 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2675 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2679 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3))
2683 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2685 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2687 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
2688 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
2689 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2694 SetLastError(CRYPT_E_ASN1_BADTAG
);
2700 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
2701 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2702 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2706 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2707 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2711 struct AsnDecodeSequenceItem items
[] = {
2712 { offsetof(CERT_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
2713 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
2714 { offsetof(CERT_INFO
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2715 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2716 SerialNumber
.pbData
), 0 },
2717 { offsetof(CERT_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
2718 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2719 SignatureAlgorithm
.pszObjId
), 0 },
2720 { offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
2721 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2723 { offsetof(CERT_INFO
, NotBefore
), CRYPT_AsnDecodeValidity
,
2724 sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
, FALSE
, 0 },
2725 { offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
2726 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2728 { offsetof(CERT_INFO
, SubjectPublicKeyInfo
), CRYPT_AsnDecodePubKeyInfo
,
2729 sizeof(CERT_PUBLIC_KEY_INFO
), FALSE
, TRUE
, offsetof(CERT_INFO
,
2730 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
2731 { offsetof(CERT_INFO
, IssuerUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2732 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2733 IssuerUniqueId
.pbData
), 0 },
2734 { offsetof(CERT_INFO
, SubjectUniqueId
), CRYPT_AsnDecodeBitsInternal
,
2735 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2736 SubjectUniqueId
.pbData
), 0 },
2737 { offsetof(CERT_INFO
, cExtension
), CRYPT_AsnDecodeCertExtensions
,
2738 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CERT_INFO
,
2742 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2743 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2744 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2746 __EXCEPT(page_fault
)
2748 SetLastError(STATUS_ACCESS_VIOLATION
);
2755 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2756 DWORD dwFlags
, PCRL_ENTRY entry
, DWORD
*pcbEntry
)
2759 struct AsnDecodeSequenceItem items
[] = {
2760 { offsetof(CRL_ENTRY
, SerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2761 sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
, offsetof(CRL_ENTRY
,
2762 SerialNumber
.pbData
), 0 },
2763 { offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
2764 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2765 { offsetof(CRL_ENTRY
, cExtension
), CRYPT_AsnDecodeExtensionsInternal
,
2766 sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
, offsetof(CRL_ENTRY
,
2770 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
2773 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
2774 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2775 NULL
, entry
, pcbEntry
, entry
? entry
->SerialNumber
.pbData
: NULL
);
2776 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
2780 typedef struct _WINE_CRL_ENTRIES
{
2782 PCRL_ENTRY rgCRLEntry
;
2783 } WINE_CRL_ENTRIES
, *PWINE_CRL_ENTRIES
;
2785 /* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
2786 * been set prior to calling.
2788 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
2789 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2790 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2794 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2795 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2797 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
2799 DWORD dataLen
, bytesNeeded
;
2801 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2803 DWORD cCRLEntry
= 0;
2804 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2806 bytesNeeded
= sizeof(WINE_CRL_ENTRIES
);
2812 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2813 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
2816 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
2817 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
2823 bytesNeeded
+= size
;
2824 ret
= CRYPT_GetLen(ptr
,
2825 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2827 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2834 *pcbStructInfo
= bytesNeeded
;
2835 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2836 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2841 PWINE_CRL_ENTRIES entries
;
2843 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2844 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2845 *pcbStructInfo
= bytesNeeded
;
2846 entries
= (PWINE_CRL_ENTRIES
)pvStructInfo
;
2847 entries
->cCRLEntry
= cCRLEntry
;
2848 assert(entries
->rgCRLEntry
);
2849 nextData
= (BYTE
*)entries
->rgCRLEntry
+
2850 entries
->cCRLEntry
* sizeof(CRL_ENTRY
);
2851 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2852 i
< cCRLEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
2855 entries
->rgCRLEntry
[i
].SerialNumber
.pbData
= nextData
;
2857 ret
= CRYPT_AsnDecodeCRLEntry(ptr
,
2858 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
2859 &entries
->rgCRLEntry
[i
], &size
);
2864 bytesNeeded
-= size
;
2865 /* Increment nextData by the difference of the
2866 * minimum size and the actual size.
2868 if (size
> sizeof(CRL_ENTRY
))
2869 nextData
+= size
- sizeof(CRL_ENTRY
);
2870 ret
= CRYPT_GetLen(ptr
,
2871 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2873 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2882 SetLastError(CRYPT_E_ASN1_BADTAG
);
2885 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
2889 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
2890 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2891 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2895 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2896 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2900 struct AsnDecodeSequenceItem items
[] = {
2901 { offsetof(CRL_INFO
, dwVersion
), CRYPT_AsnDecodeCertVersion
,
2902 sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
2903 { offsetof(CRL_INFO
, SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
2904 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
, offsetof(CRL_INFO
,
2905 SignatureAlgorithm
.pszObjId
), 0 },
2906 { offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
2907 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
2909 { offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
2910 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
2911 { offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
2912 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
2913 { offsetof(CRL_INFO
, cCRLEntry
), CRYPT_AsnDecodeCRLEntries
,
2914 sizeof(WINE_CRL_ENTRIES
), TRUE
, TRUE
, offsetof(CRL_INFO
,
2916 /* Note that the extensions are ignored by MS, so I'll ignore them too
2918 { offsetof(CRL_INFO
, cExtension
), NULL
,
2919 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
2922 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2923 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2924 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2926 __EXCEPT(page_fault
)
2928 SetLastError(STATUS_ACCESS_VIOLATION
);
2933 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
2937 /* Differences between this and CRYPT_AsnDecodeOid:
2938 * - pvStructInfo is a LPSTR *, not an LPSTR
2939 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
2940 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
2943 static BOOL WINAPI
CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType
,
2944 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2945 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2949 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2950 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2952 ret
= CRYPT_AsnDecodeOid(pbEncoded
, cbEncoded
, dwFlags
,
2953 pvStructInfo
? *(LPSTR
*)pvStructInfo
: NULL
, pcbStructInfo
);
2954 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
2955 *pcbStructInfo
+= sizeof(LPSTR
);
2956 if (ret
&& pvStructInfo
)
2957 TRACE("returning %s\n", debugstr_a(*(LPSTR
*)pvStructInfo
));
2961 /* Warning: assumes ext->pszObjId is set ahead of time! */
2962 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2963 DWORD dwFlags
, CERT_EXTENSION
*ext
, DWORD
*pcbExt
)
2965 struct AsnDecodeSequenceItem items
[] = {
2966 { offsetof(CERT_EXTENSION
, pszObjId
), CRYPT_AsnDecodeOidWrapper
,
2967 sizeof(LPSTR
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
, pszObjId
), 0 },
2968 { offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
2969 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
2970 { offsetof(CERT_EXTENSION
, Value
), CRYPT_AsnDecodeOctetsInternal
,
2971 sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
, offsetof(CERT_EXTENSION
,
2976 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
2980 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
2981 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
2982 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
2983 ext
, pcbExt
, ext
? ext
->pszObjId
: NULL
);
2985 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
2986 debugstr_a(ext
->pszObjId
));
2987 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2991 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
2992 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2993 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2997 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2998 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3000 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3002 DWORD dataLen
, bytesNeeded
;
3004 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3006 DWORD cExtension
= 0;
3007 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3009 bytesNeeded
= sizeof(CERT_EXTENSIONS
);
3015 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3016 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3019 ret
= CRYPT_AsnDecodeExtension(ptr
,
3020 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3026 bytesNeeded
+= size
;
3027 ret
= CRYPT_GetLen(ptr
,
3028 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3030 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3037 *pcbStructInfo
= bytesNeeded
;
3038 else if (*pcbStructInfo
< bytesNeeded
)
3040 SetLastError(ERROR_MORE_DATA
);
3041 *pcbStructInfo
= bytesNeeded
;
3049 CERT_EXTENSIONS
*exts
;
3051 *pcbStructInfo
= bytesNeeded
;
3052 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3053 exts
->cExtension
= cExtension
;
3054 assert(exts
->rgExtension
);
3055 nextData
= (BYTE
*)exts
->rgExtension
+
3056 exts
->cExtension
* sizeof(CERT_EXTENSION
);
3057 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3058 i
< cExtension
&& ptr
- pbEncoded
- 1 - lenBytes
<
3061 exts
->rgExtension
[i
].pszObjId
= (LPSTR
)nextData
;
3063 ret
= CRYPT_AsnDecodeExtension(ptr
,
3064 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3065 &exts
->rgExtension
[i
], &size
);
3070 bytesNeeded
-= size
;
3071 if (size
> sizeof(CERT_EXTENSION
))
3072 nextData
+= size
- sizeof(CERT_EXTENSION
);
3073 ret
= CRYPT_GetLen(ptr
,
3074 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3076 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3085 SetLastError(CRYPT_E_ASN1_BADTAG
);
3091 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3092 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3093 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3099 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3100 lpszStructType
, pbEncoded
, cbEncoded
,
3101 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3102 if (ret
&& pvStructInfo
)
3104 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3105 pcbStructInfo
, *pcbStructInfo
);
3108 CERT_EXTENSIONS
*exts
;
3110 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3111 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3112 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3113 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3114 sizeof(CERT_EXTENSIONS
));
3115 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3116 lpszStructType
, pbEncoded
, cbEncoded
,
3117 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3122 __EXCEPT(page_fault
)
3124 SetLastError(STATUS_ACCESS_VIOLATION
);
3131 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3132 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3133 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
)
3137 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, pszObjId
,
3142 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3146 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3148 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3153 /* The largest possible string for the first two components
3154 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3159 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3160 pbEncoded
[1 + lenBytes
] / 40,
3161 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3163 bytesNeeded
= strlen(firstTwo
) + 1;
3164 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3165 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3167 /* large enough for ".4000000" */
3171 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3178 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3181 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3188 snprintf(str
, sizeof(str
), ".%d", val
);
3189 bytesNeeded
+= strlen(str
);
3193 *pcbObjId
= bytesNeeded
;
3194 else if (*pcbObjId
< bytesNeeded
)
3196 *pcbObjId
= bytesNeeded
;
3197 SetLastError(ERROR_MORE_DATA
);
3203 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3204 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3206 pszObjId
+= strlen(pszObjId
);
3207 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3208 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3212 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3221 sprintf(pszObjId
, ".%d", val
);
3222 pszObjId
+= strlen(pszObjId
);
3228 *pcbObjId
= bytesNeeded
;
3233 SetLastError(CRYPT_E_ASN1_BADTAG
);
3237 __EXCEPT(page_fault
)
3239 SetLastError(STATUS_ACCESS_VIOLATION
);
3246 /* Warning: this assumes the address of value->Value.pbData is already set, in
3247 * order to avoid overwriting memory. (In some cases, it may change it, if it
3248 * doesn't copy anything to memory.) Be sure to set it correctly!
3250 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(const BYTE
*pbEncoded
,
3251 DWORD cbEncoded
, DWORD dwFlags
, CERT_NAME_VALUE
*value
, DWORD
*pcbValue
)
3259 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3261 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3263 switch (pbEncoded
[0])
3265 case ASN_NUMERICSTRING
:
3266 case ASN_PRINTABLESTRING
:
3270 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3271 SetLastError(OSS_UNIMPLEMENTED
);
3276 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3278 switch (pbEncoded
[0])
3280 case ASN_NUMERICSTRING
:
3281 case ASN_PRINTABLESTRING
:
3283 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3284 bytesNeeded
+= dataLen
;
3288 *pcbValue
= bytesNeeded
;
3289 else if (*pcbValue
< bytesNeeded
)
3291 *pcbValue
= bytesNeeded
;
3292 SetLastError(ERROR_MORE_DATA
);
3297 *pcbValue
= bytesNeeded
;
3298 switch (pbEncoded
[0])
3300 case ASN_NUMERICSTRING
:
3301 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3303 case ASN_PRINTABLESTRING
:
3304 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3307 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3312 switch (pbEncoded
[0])
3314 case ASN_NUMERICSTRING
:
3315 case ASN_PRINTABLESTRING
:
3317 value
->Value
.cbData
= dataLen
;
3318 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3319 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3323 assert(value
->Value
.pbData
);
3324 memcpy(value
->Value
.pbData
,
3325 pbEncoded
+ 1 + lenBytes
, dataLen
);
3332 value
->Value
.cbData
= 0;
3333 value
->Value
.pbData
= NULL
;
3339 __EXCEPT(page_fault
)
3341 SetLastError(STATUS_ACCESS_VIOLATION
);
3348 /* FIXME: this should use CRYPT_AsnDecodeSequence (though that won't accept it
3349 * at the moment because of the ASN_CONSTRUCTOR tag.)
3351 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
,
3352 DWORD cbEncoded
, DWORD dwFlags
, CERT_RDN_ATTR
*attr
, DWORD
*pcbAttr
)
3358 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCE
))
3360 DWORD bytesNeeded
, dataLen
, size
;
3363 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3365 /* The data length must be at least 4, two for the tag and
3366 * length for the OID, and two for the string (assuming both
3367 * have short-form lengths.)
3371 SetLastError(CRYPT_E_ASN1_EOD
);
3376 bytesNeeded
= sizeof(CERT_RDN_ATTR
);
3377 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3378 ret
= CRYPT_AsnDecodeOid(pbEncoded
+ 1 + lenBytes
,
3379 cbEncoded
- 1 - lenBytes
, dwFlags
, NULL
, &size
);
3382 /* ugly: need to know the size of the next element of
3383 * the sequence, so get it directly
3385 DWORD objIdOfset
= 1 + lenBytes
, objIdLen
,
3386 nameValueOffset
= 0;
3388 ret
= CRYPT_GetLen(pbEncoded
+ objIdOfset
,
3389 cbEncoded
- objIdOfset
, &objIdLen
);
3390 bytesNeeded
+= size
;
3391 /* hack: like encoding, this takes advantage of the
3392 * fact that the rest of the structure is identical to
3393 * a CERT_NAME_VALUE.
3397 nameValueOffset
= objIdOfset
+ objIdLen
+ 1 +
3398 GET_LEN_BYTES(pbEncoded
[objIdOfset
]);
3399 ret
= CRYPT_AsnDecodeNameValue(
3400 pbEncoded
+ nameValueOffset
,
3401 cbEncoded
- nameValueOffset
, dwFlags
, NULL
, &size
);
3405 bytesNeeded
+= size
;
3407 *pcbAttr
= bytesNeeded
;
3408 else if (*pcbAttr
< bytesNeeded
)
3410 *pcbAttr
= bytesNeeded
;
3411 SetLastError(ERROR_MORE_DATA
);
3416 BYTE
*originalData
= attr
->Value
.pbData
;
3418 *pcbAttr
= bytesNeeded
;
3419 /* strange: decode the value first, because it
3420 * has a counted size, and we can store the OID
3421 * after it. Keep track of the original data
3422 * pointer, we'll need to know whether it was
3426 ret
= CRYPT_AsnDecodeNameValue(
3427 pbEncoded
+ nameValueOffset
,
3428 cbEncoded
- nameValueOffset
, dwFlags
,
3429 (CERT_NAME_VALUE
*)&attr
->dwValueType
, &size
);
3434 /* if the data were copied to the
3435 * original location, the OID goes
3436 * after. Otherwise it goes in the
3437 * spot originally reserved for the
3440 if (attr
->Value
.pbData
== originalData
)
3442 (LPSTR
)(attr
->Value
.pbData
+
3443 attr
->Value
.cbData
);
3446 (LPSTR
)originalData
;
3447 size
= bytesNeeded
- size
;
3448 ret
= CRYPT_AsnDecodeOid(
3449 pbEncoded
+ objIdOfset
,
3450 cbEncoded
- objIdOfset
,
3451 dwFlags
, attr
->pszObjId
, &size
);
3454 attr
->pszObjId
= NULL
;
3464 SetLastError(CRYPT_E_ASN1_BADTAG
);
3468 __EXCEPT(page_fault
)
3470 SetLastError(STATUS_ACCESS_VIOLATION
);
3477 static BOOL WINAPI
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3478 DWORD dwFlags
, CERT_RDN
*rdn
, DWORD
*pcbRdn
)
3484 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SETOF
))
3488 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3490 DWORD bytesNeeded
, cRDNAttr
= 0;
3491 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3493 bytesNeeded
= sizeof(CERT_RDN
);
3499 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3500 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3502 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3503 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3509 bytesNeeded
+= size
;
3510 ret
= CRYPT_GetLen(ptr
,
3511 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3513 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3520 *pcbRdn
= bytesNeeded
;
3521 else if (*pcbRdn
< bytesNeeded
)
3523 *pcbRdn
= bytesNeeded
;
3524 SetLastError(ERROR_MORE_DATA
);
3533 *pcbRdn
= bytesNeeded
;
3534 rdn
->cRDNAttr
= cRDNAttr
;
3535 rdn
->rgRDNAttr
= (CERT_RDN_ATTR
*)((BYTE
*)rdn
+
3537 nextData
= (BYTE
*)rdn
->rgRDNAttr
+
3538 rdn
->cRDNAttr
* sizeof(CERT_RDN_ATTR
);
3539 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3540 i
< cRDNAttr
&& ptr
- pbEncoded
- 1 - lenBytes
<
3543 rdn
->rgRDNAttr
[i
].Value
.pbData
= nextData
;
3545 ret
= CRYPT_AsnDecodeRdnAttr(ptr
,
3546 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3547 &rdn
->rgRDNAttr
[i
], &size
);
3552 bytesNeeded
-= size
;
3553 /* If dwFlags & CRYPT_DECODE_NOCOPY_FLAG, the
3554 * data may not have been copied.
3556 if (rdn
->rgRDNAttr
[i
].Value
.pbData
== nextData
)
3558 rdn
->rgRDNAttr
[i
].Value
.cbData
;
3559 /* Ugly: the OID, if copied, is stored in
3560 * memory after the value, so increment by its
3561 * string length if it's set and points here.
3563 if ((const BYTE
*)rdn
->rgRDNAttr
[i
].pszObjId
3566 rdn
->rgRDNAttr
[i
].pszObjId
) + 1;
3567 ret
= CRYPT_GetLen(ptr
,
3568 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3570 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3579 SetLastError(CRYPT_E_ASN1_BADTAG
);
3583 __EXCEPT(page_fault
)
3585 SetLastError(STATUS_ACCESS_VIOLATION
);
3592 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3593 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3594 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3600 if (pbEncoded
[0] == (ASN_CONSTRUCTOR
| ASN_SEQUENCEOF
))
3604 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3606 DWORD bytesNeeded
, cRDN
= 0;
3607 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3609 bytesNeeded
= sizeof(CERT_NAME_INFO
);
3614 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3615 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3619 ret
= CRYPT_AsnDecodeRdn(ptr
,
3620 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3626 bytesNeeded
+= size
;
3627 ret
= CRYPT_GetLen(ptr
,
3628 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3630 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3637 *pcbStructInfo
= bytesNeeded
;
3638 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3639 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3641 CERT_NAME_INFO
*info
;
3643 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3644 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3645 info
= (CERT_NAME_INFO
*)pvStructInfo
;
3647 if (info
->cRDN
== 0)
3655 info
->rgRDN
= (CERT_RDN
*)((BYTE
*)pvStructInfo
+
3656 sizeof(CERT_NAME_INFO
));
3657 nextData
= (BYTE
*)info
->rgRDN
+
3658 info
->cRDN
* sizeof(CERT_RDN
);
3659 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3660 i
< cRDN
&& ptr
- pbEncoded
- 1 - lenBytes
<
3663 info
->rgRDN
[i
].rgRDNAttr
=
3664 (CERT_RDN_ATTR
*)nextData
;
3666 ret
= CRYPT_AsnDecodeRdn(ptr
,
3667 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
3668 &info
->rgRDN
[i
], &size
);
3674 bytesNeeded
-= size
;
3675 ret
= CRYPT_GetLen(ptr
,
3676 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3678 ptr
+= nextLen
+ 1 +
3679 GET_LEN_BYTES(ptr
[1]);
3689 SetLastError(CRYPT_E_ASN1_BADTAG
);
3693 __EXCEPT(page_fault
)
3695 SetLastError(STATUS_ACCESS_VIOLATION
);
3702 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
3703 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3704 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3707 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
3709 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3710 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3712 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3713 bytesNeeded
+= cbEncoded
;
3715 *pcbStructInfo
= bytesNeeded
;
3716 else if (*pcbStructInfo
< bytesNeeded
)
3718 SetLastError(ERROR_MORE_DATA
);
3719 *pcbStructInfo
= bytesNeeded
;
3724 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
3726 *pcbStructInfo
= bytesNeeded
;
3727 blob
->cbData
= cbEncoded
;
3728 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3729 blob
->pbData
= (LPBYTE
)pbEncoded
;
3732 assert(blob
->pbData
);
3733 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3739 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3740 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3741 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3743 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3744 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3746 struct AsnDecodeSequenceItem items
[] = {
3747 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
3748 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3749 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
3750 { offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
3751 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
3752 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
3755 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3756 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3758 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3759 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3760 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
3761 if (ret
&& pvStructInfo
)
3763 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
3764 debugstr_a(algo
->pszObjId
));
3769 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
3770 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3771 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3777 struct AsnDecodeSequenceItem items
[] = {
3778 { offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
3779 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3780 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
3781 Algorithm
.pszObjId
) },
3782 { offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
3783 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
3784 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
3787 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3788 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3789 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3791 __EXCEPT(page_fault
)
3793 SetLastError(STATUS_ACCESS_VIOLATION
);
3800 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
3801 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3802 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3808 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3811 if (pbEncoded
[0] != ASN_BOOL
)
3813 SetLastError(CRYPT_E_ASN1_BADTAG
);
3816 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
3818 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3821 if (pbEncoded
[1] > 1)
3823 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3828 *pcbStructInfo
= sizeof(BOOL
);
3831 else if (*pcbStructInfo
< sizeof(BOOL
))
3833 *pcbStructInfo
= sizeof(BOOL
);
3834 SetLastError(ERROR_MORE_DATA
);
3839 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
3842 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3846 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3847 DWORD dwFlags
, CERT_ALT_NAME_ENTRY
*entry
, DWORD
*pcbEntry
)
3849 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
3854 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3857 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
3859 SetLastError(CRYPT_E_ASN1_BADTAG
);
3862 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3863 if (1 + lenBytes
> cbEncoded
)
3865 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3868 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3870 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
3872 case 1: /* rfc822Name */
3873 case 2: /* dNSName */
3874 case 6: /* uniformResourceIdentifier */
3875 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
3877 case 7: /* iPAddress */
3878 bytesNeeded
+= dataLen
;
3880 case 8: /* registeredID */
3881 /* FIXME: decode as OID */
3882 case 0: /* otherName */
3883 case 4: /* directoryName */
3885 SetLastError(CRYPT_E_ASN1_BADTAG
);
3888 case 3: /* x400Address, unimplemented */
3889 case 5: /* ediPartyName, unimplemented */
3890 SetLastError(CRYPT_E_ASN1_BADTAG
);
3894 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3900 *pcbEntry
= bytesNeeded
;
3901 else if (*pcbEntry
< bytesNeeded
)
3903 SetLastError(ERROR_MORE_DATA
);
3908 /* MS used values one greater than the asn1 ones.. sigh */
3909 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
3910 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
3912 case 1: /* rfc822Name */
3913 case 2: /* dNSName */
3914 case 6: /* uniformResourceIdentifier */
3918 for (i
= 0; i
< dataLen
; i
++)
3919 entry
->u
.pwszURL
[i
] =
3920 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
3921 entry
->u
.pwszURL
[i
] = 0;
3924 case 7: /* iPAddress */
3925 /* The next data pointer is in the pwszURL spot, that is,
3926 * the first 4 bytes. Need to move it to the next spot.
3928 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
3929 entry
->u
.IPAddress
.cbData
= dataLen
;
3930 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
3940 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
3941 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3942 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3948 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3952 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3954 DWORD bytesNeeded
, cEntry
= 0;
3955 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3957 bytesNeeded
= sizeof(CERT_ALT_NAME_INFO
);
3962 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
3963 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3967 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
3968 cbEncoded
- (ptr
- pbEncoded
), dwFlags
, NULL
, &size
);
3974 bytesNeeded
+= size
;
3975 ret
= CRYPT_GetLen(ptr
,
3976 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
3978 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
3985 *pcbStructInfo
= bytesNeeded
;
3986 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3987 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3989 CERT_ALT_NAME_INFO
*info
;
3991 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3992 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3993 info
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
3994 info
->cAltEntry
= 0;
3996 info
->rgAltEntry
= NULL
;
4004 (CERT_ALT_NAME_ENTRY
*)((BYTE
*)pvStructInfo
+
4005 sizeof(CERT_ALT_NAME_INFO
));
4006 nextData
= (BYTE
*)info
->rgAltEntry
+
4007 cEntry
* sizeof(CERT_ALT_NAME_ENTRY
);
4008 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
4009 i
< cEntry
&& ptr
- pbEncoded
- 1 - lenBytes
<
4012 info
->rgAltEntry
[i
].u
.pwszURL
=
4015 ret
= CRYPT_AsnDecodeAltNameEntry(ptr
,
4016 cbEncoded
- (ptr
- pbEncoded
), dwFlags
,
4017 &info
->rgAltEntry
[i
], &size
);
4024 sizeof(CERT_ALT_NAME_ENTRY
);
4025 bytesNeeded
-= size
;
4026 ret
= CRYPT_GetLen(ptr
,
4027 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
4029 ptr
+= nextLen
+ 1 +
4030 GET_LEN_BYTES(ptr
[1]);
4040 SetLastError(CRYPT_E_ASN1_BADTAG
);
4044 __EXCEPT(page_fault
)
4046 SetLastError(STATUS_ACCESS_VIOLATION
);
4053 struct PATH_LEN_CONSTRAINT
4055 BOOL fPathLenConstraint
;
4056 DWORD dwPathLenConstraint
;
4059 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
4060 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4061 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4067 if (pbEncoded
[0] == ASN_INTEGER
)
4069 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
4072 *pcbStructInfo
= bytesNeeded
;
4073 else if (*pcbStructInfo
< bytesNeeded
)
4075 SetLastError(ERROR_MORE_DATA
);
4076 *pcbStructInfo
= bytesNeeded
;
4081 struct PATH_LEN_CONSTRAINT
*constraint
=
4082 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
4083 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
4085 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
4086 pbEncoded
, cbEncoded
, 0, NULL
,
4087 &constraint
->dwPathLenConstraint
, &size
);
4089 constraint
->fPathLenConstraint
= TRUE
;
4090 TRACE("got an int, dwPathLenConstraint is %ld\n",
4091 constraint
->dwPathLenConstraint
);
4096 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4100 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4104 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
4105 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4106 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4112 struct AsnDecodeSequenceItem items
[] = {
4113 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
), CRYPT_AsnDecodeBool
,
4114 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
4115 { offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fPathLenConstraint
),
4116 CRYPT_AsnDecodePathLenConstraint
, sizeof(struct PATH_LEN_CONSTRAINT
),
4117 TRUE
, FALSE
, 0, 0 },
4120 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4121 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4122 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4124 __EXCEPT(page_fault
)
4126 SetLastError(STATUS_ACCESS_VIOLATION
);
4133 #define RSA1_MAGIC 0x31415352
4135 struct DECODED_RSA_PUB_KEY
4138 CRYPT_INTEGER_BLOB modulus
;
4141 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4142 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4143 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4149 struct AsnDecodeSequenceItem items
[] = {
4150 { offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4151 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4152 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4154 { offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4155 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4157 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4160 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4161 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4162 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4165 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4166 decodedKey
->modulus
.cbData
;
4170 *pcbStructInfo
= bytesNeeded
;
4173 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4174 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4177 RSAPUBKEY
*rsaPubKey
;
4179 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4180 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4181 hdr
= (BLOBHEADER
*)pvStructInfo
;
4182 hdr
->bType
= PUBLICKEYBLOB
;
4183 hdr
->bVersion
= CUR_BLOB_VERSION
;
4185 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4186 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4187 sizeof(BLOBHEADER
));
4188 rsaPubKey
->magic
= RSA1_MAGIC
;
4189 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4190 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4191 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4192 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4193 decodedKey
->modulus
.cbData
);
4195 LocalFree(decodedKey
);
4198 __EXCEPT(page_fault
)
4200 SetLastError(STATUS_ACCESS_VIOLATION
);
4207 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
4208 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4209 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4213 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4214 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4216 if (pbEncoded
[0] == ASN_OCTETSTRING
)
4218 DWORD bytesNeeded
, dataLen
;
4220 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4222 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4223 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4225 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4227 *pcbStructInfo
= bytesNeeded
;
4228 else if (*pcbStructInfo
< bytesNeeded
)
4230 SetLastError(ERROR_MORE_DATA
);
4231 *pcbStructInfo
= bytesNeeded
;
4236 CRYPT_DATA_BLOB
*blob
;
4237 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4239 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4240 blob
->cbData
= dataLen
;
4241 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4242 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4245 assert(blob
->pbData
);
4247 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4255 SetLastError(CRYPT_E_ASN1_BADTAG
);
4261 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4262 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4263 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4267 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4268 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4274 if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4275 lpszStructType
, pbEncoded
, cbEncoded
,
4276 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4279 *pcbStructInfo
= bytesNeeded
;
4280 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4281 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4283 CRYPT_DATA_BLOB
*blob
;
4285 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4286 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4287 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4288 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
4289 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4290 lpszStructType
, pbEncoded
, cbEncoded
,
4291 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4297 SetLastError(CRYPT_E_ASN1_BADTAG
);
4301 __EXCEPT(page_fault
)
4303 SetLastError(STATUS_ACCESS_VIOLATION
);
4310 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4311 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4312 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4316 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4317 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4319 if (pbEncoded
[0] == ASN_BITSTRING
)
4321 DWORD bytesNeeded
, dataLen
;
4323 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4325 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4326 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4328 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4330 *pcbStructInfo
= bytesNeeded
;
4331 else if (*pcbStructInfo
< bytesNeeded
)
4333 *pcbStructInfo
= bytesNeeded
;
4334 SetLastError(ERROR_MORE_DATA
);
4339 CRYPT_BIT_BLOB
*blob
;
4341 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4342 blob
->cbData
= dataLen
- 1;
4343 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4344 GET_LEN_BYTES(pbEncoded
[1]));
4345 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4347 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4348 GET_LEN_BYTES(pbEncoded
[1]);
4352 assert(blob
->pbData
);
4355 BYTE mask
= 0xff << blob
->cUnusedBits
;
4357 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4358 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4359 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4367 SetLastError(CRYPT_E_ASN1_BADTAG
);
4370 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4374 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4375 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4376 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4380 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4381 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4387 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4388 lpszStructType
, pbEncoded
, cbEncoded
,
4389 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4392 *pcbStructInfo
= bytesNeeded
;
4393 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4394 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4396 CRYPT_BIT_BLOB
*blob
;
4398 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4399 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4400 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4401 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4402 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4403 lpszStructType
, pbEncoded
, cbEncoded
,
4404 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4409 __EXCEPT(page_fault
)
4411 SetLastError(STATUS_ACCESS_VIOLATION
);
4415 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4419 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4420 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4421 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4427 *pcbStructInfo
= sizeof(int);
4432 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4433 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4434 DWORD size
= sizeof(buf
);
4436 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4437 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4438 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4441 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4442 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4446 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4447 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4448 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4450 /* initialize to a negative value to sign-extend */
4455 for (i
= 0; i
< blob
->cbData
; i
++)
4458 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4460 memcpy(pvStructInfo
, &val
, sizeof(int));
4463 else if (GetLastError() == ERROR_MORE_DATA
)
4464 SetLastError(CRYPT_E_ASN1_LARGE
);
4466 __EXCEPT(page_fault
)
4468 SetLastError(STATUS_ACCESS_VIOLATION
);
4475 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4476 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4477 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4481 if (pbEncoded
[0] == ASN_INTEGER
)
4483 DWORD bytesNeeded
, dataLen
;
4485 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4487 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4489 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4491 *pcbStructInfo
= bytesNeeded
;
4492 else if (*pcbStructInfo
< bytesNeeded
)
4494 *pcbStructInfo
= bytesNeeded
;
4495 SetLastError(ERROR_MORE_DATA
);
4500 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4502 blob
->cbData
= dataLen
;
4503 assert(blob
->pbData
);
4508 for (i
= 0; i
< blob
->cbData
; i
++)
4510 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4519 SetLastError(CRYPT_E_ASN1_BADTAG
);
4525 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4526 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4527 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4535 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4536 lpszStructType
, pbEncoded
, cbEncoded
,
4537 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4540 *pcbStructInfo
= bytesNeeded
;
4541 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4542 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4544 CRYPT_INTEGER_BLOB
*blob
;
4546 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4547 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4548 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4549 blob
->pbData
= (BYTE
*)pvStructInfo
+
4550 sizeof(CRYPT_INTEGER_BLOB
);
4551 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4552 lpszStructType
, pbEncoded
, cbEncoded
,
4553 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4558 __EXCEPT(page_fault
)
4560 SetLastError(STATUS_ACCESS_VIOLATION
);
4567 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
4568 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
4569 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4570 void *pvStructInfo
, DWORD
*pcbStructInfo
)
4574 if (pbEncoded
[0] == ASN_INTEGER
)
4576 DWORD bytesNeeded
, dataLen
;
4578 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4580 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4582 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4584 *pcbStructInfo
= bytesNeeded
;
4585 else if (*pcbStructInfo
< bytesNeeded
)
4587 *pcbStructInfo
= bytesNeeded
;
4588 SetLastError(ERROR_MORE_DATA
);
4593 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4595 blob
->cbData
= dataLen
;
4596 assert(blob
->pbData
);
4597 /* remove leading zero byte if it exists */
4598 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4607 for (i
= 0; i
< blob
->cbData
; i
++)
4609 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4618 SetLastError(CRYPT_E_ASN1_BADTAG
);
4624 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4625 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4626 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4634 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4635 lpszStructType
, pbEncoded
, cbEncoded
,
4636 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4639 *pcbStructInfo
= bytesNeeded
;
4640 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4641 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4643 CRYPT_INTEGER_BLOB
*blob
;
4645 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4646 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4647 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4648 blob
->pbData
= (BYTE
*)pvStructInfo
+
4649 sizeof(CRYPT_INTEGER_BLOB
);
4650 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4651 lpszStructType
, pbEncoded
, cbEncoded
,
4652 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4657 __EXCEPT(page_fault
)
4659 SetLastError(STATUS_ACCESS_VIOLATION
);
4666 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4667 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4668 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4674 *pcbStructInfo
= sizeof(int);
4679 if (pbEncoded
[0] == ASN_ENUMERATED
)
4681 unsigned int val
= 0, i
;
4685 SetLastError(CRYPT_E_ASN1_EOD
);
4688 else if (pbEncoded
[1] == 0)
4690 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4695 /* A little strange looking, but we have to accept a sign byte:
4696 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4697 * assuming a small length is okay here, it has to be in short
4700 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4702 SetLastError(CRYPT_E_ASN1_LARGE
);
4705 for (i
= 0; i
< pbEncoded
[1]; i
++)
4708 val
|= pbEncoded
[2 + i
];
4710 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4711 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4713 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4714 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4715 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4721 SetLastError(CRYPT_E_ASN1_BADTAG
);
4725 __EXCEPT(page_fault
)
4727 SetLastError(STATUS_ACCESS_VIOLATION
);
4734 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4737 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4742 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4744 if (!isdigit(*(pbEncoded))) \
4746 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4752 (word) += *(pbEncoded)++ - '0'; \
4757 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
4758 SYSTEMTIME
*sysTime
)
4765 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
4767 WORD hours
, minutes
= 0;
4768 BYTE sign
= *pbEncoded
++;
4771 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
4772 if (ret
&& hours
>= 24)
4774 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4779 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
4780 if (ret
&& minutes
>= 60)
4782 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4790 sysTime
->wHour
+= hours
;
4791 sysTime
->wMinute
+= minutes
;
4795 if (hours
> sysTime
->wHour
)
4798 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
4801 sysTime
->wHour
-= hours
;
4802 if (minutes
> sysTime
->wMinute
)
4805 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
4808 sysTime
->wMinute
-= minutes
;
4813 __EXCEPT(page_fault
)
4815 SetLastError(STATUS_ACCESS_VIOLATION
);
4822 #define MIN_ENCODED_TIME_LENGTH 10
4824 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
4825 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4826 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4832 *pcbStructInfo
= sizeof(FILETIME
);
4838 if (pbEncoded
[0] == ASN_UTCTIME
)
4842 SetLastError(CRYPT_E_ASN1_EOD
);
4845 else if (pbEncoded
[1] > 0x7f)
4847 /* long-form date strings really can't be valid */
4848 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4853 SYSTEMTIME sysTime
= { 0 };
4854 BYTE len
= pbEncoded
[1];
4856 if (len
< MIN_ENCODED_TIME_LENGTH
)
4858 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4864 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
4865 if (sysTime
.wYear
>= 50)
4866 sysTime
.wYear
+= 1900;
4868 sysTime
.wYear
+= 2000;
4869 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
4870 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
4871 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
4872 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
4875 if (len
>= 2 && isdigit(*pbEncoded
) &&
4876 isdigit(*(pbEncoded
+ 1)))
4877 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4879 else if (isdigit(*pbEncoded
))
4880 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
4883 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
4886 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4887 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4890 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4891 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4892 ret
= SystemTimeToFileTime(&sysTime
,
4893 (FILETIME
*)pvStructInfo
);
4900 SetLastError(CRYPT_E_ASN1_BADTAG
);
4904 __EXCEPT(page_fault
)
4906 SetLastError(STATUS_ACCESS_VIOLATION
);
4913 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
4914 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4915 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4921 *pcbStructInfo
= sizeof(FILETIME
);
4927 if (pbEncoded
[0] == ASN_GENERALTIME
)
4931 SetLastError(CRYPT_E_ASN1_EOD
);
4934 else if (pbEncoded
[1] > 0x7f)
4936 /* long-form date strings really can't be valid */
4937 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4942 BYTE len
= pbEncoded
[1];
4944 if (len
< MIN_ENCODED_TIME_LENGTH
)
4946 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4951 SYSTEMTIME sysTime
= { 0 };
4954 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
4955 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
4956 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
4957 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
4960 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4963 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4965 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
4972 /* workaround macro weirdness */
4973 digits
= min(len
, 3);
4974 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
4975 sysTime
.wMilliseconds
);
4978 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
4981 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4982 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4985 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4986 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4987 ret
= SystemTimeToFileTime(&sysTime
,
4988 (FILETIME
*)pvStructInfo
);
4995 SetLastError(CRYPT_E_ASN1_BADTAG
);
4999 __EXCEPT(page_fault
)
5001 SetLastError(STATUS_ACCESS_VIOLATION
);
5008 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5009 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5010 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5016 if (pbEncoded
[0] == ASN_UTCTIME
)
5017 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5018 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5020 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5021 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5022 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5023 pvStructInfo
, pcbStructInfo
);
5026 SetLastError(CRYPT_E_ASN1_BADTAG
);
5030 __EXCEPT(page_fault
)
5032 SetLastError(STATUS_ACCESS_VIOLATION
);
5039 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5040 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5041 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5047 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5049 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5051 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5056 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5057 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5059 ptr
= pbEncoded
+ 1 + lenBytes
;
5060 remainingLen
= dataLen
;
5061 while (ret
&& remainingLen
)
5065 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5068 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5070 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5071 ptr
+= 1 + nextLenBytes
+ nextLen
;
5072 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5073 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5074 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5080 CRYPT_SEQUENCE_OF_ANY
*seq
;
5084 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5085 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5087 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5088 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5089 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5090 seq
->cValue
= cValue
;
5091 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5093 nextPtr
= (BYTE
*)seq
->rgValue
+
5094 cValue
* sizeof(CRYPT_DER_BLOB
);
5095 ptr
= pbEncoded
+ 1 + lenBytes
;
5096 remainingLen
= dataLen
;
5098 while (ret
&& remainingLen
)
5102 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5105 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5107 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5109 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5110 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5113 seq
->rgValue
[i
].pbData
= nextPtr
;
5114 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5116 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5118 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5119 ptr
+= 1 + nextLenBytes
+ nextLen
;
5129 SetLastError(CRYPT_E_ASN1_BADTAG
);
5133 __EXCEPT(page_fault
)
5135 SetLastError(STATUS_ACCESS_VIOLATION
);
5142 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5143 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5144 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5146 static HCRYPTOIDFUNCSET set
= NULL
;
5148 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5149 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5151 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5152 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5153 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5155 if (!pvStructInfo
&& !pcbStructInfo
)
5157 SetLastError(ERROR_INVALID_PARAMETER
);
5160 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5161 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5163 SetLastError(ERROR_FILE_NOT_FOUND
);
5168 SetLastError(CRYPT_E_ASN1_EOD
);
5171 if (cbEncoded
> MAX_ENCODED_LEN
)
5173 SetLastError(CRYPT_E_ASN1_LARGE
);
5177 SetLastError(NOERROR
);
5178 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5179 *(BYTE
**)pvStructInfo
= NULL
;
5180 if (!HIWORD(lpszStructType
))
5182 switch (LOWORD(lpszStructType
))
5184 case (WORD
)X509_CERT
:
5185 decodeFunc
= CRYPT_AsnDecodeCert
;
5187 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5188 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5190 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5191 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5193 case (WORD
)X509_EXTENSIONS
:
5194 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5196 case (WORD
)X509_NAME
:
5197 decodeFunc
= CRYPT_AsnDecodeName
;
5199 case (WORD
)X509_PUBLIC_KEY_INFO
:
5200 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5202 case (WORD
)X509_ALTERNATE_NAME
:
5203 decodeFunc
= CRYPT_AsnDecodeAltName
;
5205 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5206 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5208 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5209 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5211 case (WORD
)X509_OCTET_STRING
:
5212 decodeFunc
= CRYPT_AsnDecodeOctets
;
5214 case (WORD
)X509_BITS
:
5215 case (WORD
)X509_KEY_USAGE
:
5216 decodeFunc
= CRYPT_AsnDecodeBits
;
5218 case (WORD
)X509_INTEGER
:
5219 decodeFunc
= CRYPT_AsnDecodeInt
;
5221 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5222 decodeFunc
= CRYPT_AsnDecodeInteger
;
5224 case (WORD
)X509_MULTI_BYTE_UINT
:
5225 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5227 case (WORD
)X509_ENUMERATED
:
5228 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5230 case (WORD
)X509_CHOICE_OF_TIME
:
5231 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5233 case (WORD
)X509_SEQUENCE_OF_ANY
:
5234 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5236 case (WORD
)PKCS_UTC_TIME
:
5237 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5240 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5243 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5244 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5245 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5246 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5247 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5248 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5249 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5250 decodeFunc
= CRYPT_AsnDecodeBits
;
5251 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5252 decodeFunc
= CRYPT_AsnDecodeOctets
;
5253 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5254 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5255 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5256 decodeFunc
= CRYPT_AsnDecodeAltName
;
5257 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5258 decodeFunc
= CRYPT_AsnDecodeAltName
;
5259 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5260 decodeFunc
= CRYPT_AsnDecodeAltName
;
5261 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5262 decodeFunc
= CRYPT_AsnDecodeAltName
;
5263 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5264 decodeFunc
= CRYPT_AsnDecodeAltName
;
5266 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5267 debugstr_a(lpszStructType
));
5271 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
5272 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
5273 (void **)&decodeFunc
, &hFunc
);
5276 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5277 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5279 SetLastError(ERROR_FILE_NOT_FOUND
);
5281 CryptFreeOIDFunctionAddress(hFunc
, 0);
5285 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5286 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5288 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5289 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5292 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5293 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5294 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5299 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5300 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5303 if (!pszPublicKeyObjId
)
5304 pszPublicKeyObjId
= szOID_RSA_RSA
;
5305 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5309 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5312 LPBYTE pubKey
= CryptMemAlloc(keySize
);
5316 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
5320 DWORD encodedLen
= 0;
5322 ret
= CryptEncodeObject(dwCertEncodingType
,
5323 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5326 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5327 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5330 *pcbInfo
= sizeNeeded
;
5331 else if (*pcbInfo
< sizeNeeded
)
5333 SetLastError(ERROR_MORE_DATA
);
5334 *pcbInfo
= sizeNeeded
;
5339 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5340 sizeof(CERT_PUBLIC_KEY_INFO
);
5341 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5343 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5344 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5345 pInfo
->PublicKey
.pbData
=
5346 (BYTE
*)pInfo
->Algorithm
.pszObjId
5347 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5348 pInfo
->PublicKey
.cbData
= encodedLen
;
5349 pInfo
->PublicKey
.cUnusedBits
= 0;
5350 ret
= CryptEncodeObject(dwCertEncodingType
,
5351 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5352 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5356 CryptMemFree(pubKey
);
5361 CryptDestroyKey(key
);
5366 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5367 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5368 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5370 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5371 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5372 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5374 static HCRYPTOIDFUNCSET set
= NULL
;
5376 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5377 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5379 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5380 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5385 SetLastError(ERROR_INVALID_PARAMETER
);
5389 if (pszPublicKeyObjId
)
5392 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
5394 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
5395 0, (void **)&exportFunc
, &hFunc
);
5398 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
5399 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5400 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5402 CryptFreeOIDFunctionAddress(hFunc
, 0);
5406 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5407 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5409 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5413 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5414 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5415 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5418 DWORD pubKeySize
= 0;
5420 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5421 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5423 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5424 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5427 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
5431 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5432 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5435 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5437 CryptMemFree(pubKey
);
5445 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5446 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5447 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5449 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5450 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5451 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5453 static HCRYPTOIDFUNCSET set
= NULL
;
5455 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5456 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5458 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5459 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5462 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
5463 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
5464 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
5466 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
5467 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
5470 CryptFreeOIDFunctionAddress(hFunc
, 0);