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
35 #include "wine/port.h"
42 #define NONAMELESSUNION
50 #include "wine/debug.h"
51 #include "wine/exception.h"
52 #include "crypt32_private.h"
54 /* This is a bit arbitrary, but to set some limit: */
55 #define MAX_ENCODED_LEN 0x02000000
57 /* a few asn.1 tags we need */
58 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
59 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
60 #define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
61 #define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
62 #define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
63 #define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
64 #define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
65 #define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
66 #define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
68 #define ASN_FLAGS_MASK 0xe0
69 #define ASN_TYPE_MASK 0x1f
71 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
79 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
81 typedef BOOL (WINAPI
*CryptEncodeObjectExFunc
)(DWORD
, LPCSTR
, const void *,
82 DWORD
, PCRYPT_ENCODE_PARA
, BYTE
*, DWORD
*);
83 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
84 DWORD
, DWORD
, void *, DWORD
*);
85 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
86 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
88 /* Prototypes for built-in encoders/decoders. They follow the Ex style
89 * prototypes. The dwCertEncodingType and lpszStructType are ignored by the
90 * built-in functions, but the parameters are retained to simplify
91 * CryptEncodeObjectEx/CryptDecodeObjectEx, since they must call functions in
92 * external DLLs that follow these signatures.
94 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
95 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
96 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
97 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
99 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
100 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
101 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
102 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
103 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
104 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
105 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
106 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
107 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
108 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
109 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
110 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
111 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
112 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
113 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
114 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
115 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
116 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
117 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
118 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
120 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
121 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
122 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
123 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
124 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
125 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
126 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
127 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
128 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
129 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
);
131 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
132 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
133 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
134 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
135 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
136 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
137 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
138 * time, doesn't do memory allocation, and doesn't do exception handling.
139 * (This isn't intended to be the externally-called one.)
141 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
142 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
143 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
144 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
145 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
);
146 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
147 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
148 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
149 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
150 /* Internal function */
151 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
152 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
153 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
154 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
155 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
156 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
157 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
158 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
159 * member has been initialized, doesn't do exception handling, and doesn't do
162 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
163 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
164 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
165 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
166 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
167 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
168 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
169 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
170 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
171 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
172 * member has been initialized, doesn't do exception handling, and doesn't do
175 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
176 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
177 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
178 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
179 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
180 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
181 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
182 void *pvStructInfo
, DWORD
*pcbStructInfo
);
184 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
185 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
187 static HCRYPTOIDFUNCSET set
= NULL
;
189 HCRYPTOIDFUNCADDR hFunc
;
190 CryptEncodeObjectFunc pCryptEncodeObject
;
192 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
193 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
196 if (!pbEncoded
&& !pcbEncoded
)
198 SetLastError(ERROR_INVALID_PARAMETER
);
202 /* Try registered DLL first.. */
204 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
205 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
206 (void **)&pCryptEncodeObject
, &hFunc
);
207 if (pCryptEncodeObject
)
209 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
210 pvStructInfo
, pbEncoded
, pcbEncoded
);
211 CryptFreeOIDFunctionAddress(hFunc
, 0);
215 /* If not, use CryptEncodeObjectEx */
216 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
217 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
222 /* Helper function to check *pcbEncoded, set it to the required size, and
223 * optionally to allocate memory. Assumes pbEncoded is not NULL.
224 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
225 * pointer to the newly allocated memory.
227 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
228 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
233 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
235 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
236 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
238 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
239 if (!*(BYTE
**)pbEncoded
)
242 *pcbEncoded
= bytesNeeded
;
244 else if (bytesNeeded
> *pcbEncoded
)
246 *pcbEncoded
= bytesNeeded
;
247 SetLastError(ERROR_MORE_DATA
);
253 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
255 DWORD bytesNeeded
, significantBytes
= 0;
263 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
264 temp
<<= 8, significantBytes
--)
266 bytesNeeded
= significantBytes
+ 1;
270 *pcbEncoded
= bytesNeeded
;
273 if (*pcbEncoded
< bytesNeeded
)
275 SetLastError(ERROR_MORE_DATA
);
279 *pbEncoded
= (BYTE
)len
;
284 *pbEncoded
++ = significantBytes
| 0x80;
285 for (i
= 0; i
< significantBytes
; i
++)
287 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
291 *pcbEncoded
= bytesNeeded
;
295 struct AsnEncodeSequenceItem
297 const void *pvStructInfo
;
298 CryptEncodeObjectExFunc encodeFunc
;
299 DWORD size
; /* used during encoding, not for your use */
302 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
303 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
304 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
307 DWORD i
, dataLen
= 0;
309 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
310 pbEncoded
, *pcbEncoded
);
311 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
313 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
314 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
315 NULL
, &items
[i
].size
);
316 /* Some functions propagate their errors through the size */
318 *pcbEncoded
= items
[i
].size
;
319 dataLen
+= items
[i
].size
;
323 DWORD lenBytes
, bytesNeeded
;
325 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
326 bytesNeeded
= 1 + lenBytes
+ dataLen
;
328 *pcbEncoded
= bytesNeeded
;
331 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
332 pcbEncoded
, bytesNeeded
)))
334 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
335 pbEncoded
= *(BYTE
**)pbEncoded
;
336 *pbEncoded
++ = ASN_SEQUENCE
;
337 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
338 pbEncoded
+= lenBytes
;
339 for (i
= 0; ret
&& i
< cItem
; i
++)
341 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
342 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
343 NULL
, pbEncoded
, &items
[i
].size
);
344 /* Some functions propagate their errors through the size */
346 *pcbEncoded
= items
[i
].size
;
347 pbEncoded
+= items
[i
].size
;
352 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
356 struct AsnConstructedItem
359 const void *pvStructInfo
;
360 CryptEncodeObjectExFunc encodeFunc
;
363 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
364 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
365 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
368 const struct AsnConstructedItem
*item
=
369 (const struct AsnConstructedItem
*)pvStructInfo
;
372 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
373 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
375 DWORD dataLen
, bytesNeeded
;
377 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
378 bytesNeeded
= 1 + dataLen
+ len
;
380 *pcbEncoded
= bytesNeeded
;
381 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
382 pbEncoded
, pcbEncoded
, bytesNeeded
)))
384 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
385 pbEncoded
= *(BYTE
**)pbEncoded
;
386 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
387 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
388 pbEncoded
+= dataLen
;
389 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
390 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
394 /* Some functions propagate their errors through the size */
401 /* Some functions propagate their errors through the size */
407 struct AsnEncodeTagSwappedItem
410 const void *pvStructInfo
;
411 CryptEncodeObjectExFunc encodeFunc
;
414 /* Sort of a wacky hack, it encodes something using the struct
415 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
416 * given in the struct AsnEncodeTagSwappedItem.
418 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
419 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
420 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
423 const struct AsnEncodeTagSwappedItem
*item
=
424 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
426 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
427 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
428 if (ret
&& pbEncoded
)
429 *pbEncoded
= item
->tag
;
433 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
434 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
435 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
437 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
440 /* CERT_V1 is not encoded */
448 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
450 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
451 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
456 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
457 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
458 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
460 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
465 *pcbEncoded
= blob
->cbData
;
468 else if (*pcbEncoded
< blob
->cbData
)
470 *pcbEncoded
= blob
->cbData
;
471 SetLastError(ERROR_MORE_DATA
);
477 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
478 *pcbEncoded
= blob
->cbData
;
484 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
485 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
486 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
489 /* This has two filetimes in a row, a NotBefore and a NotAfter */
490 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
491 struct AsnEncodeSequenceItem items
[] = {
492 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
493 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
496 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
497 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
502 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
503 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
504 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
507 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
508 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
510 struct AsnEncodeSequenceItem items
[] = {
511 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
512 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
515 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
516 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
521 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
522 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
523 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
529 const CERT_PUBLIC_KEY_INFO
*info
=
530 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
531 struct AsnEncodeSequenceItem items
[] = {
532 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
533 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
536 TRACE("Encoding public key with OID %s\n",
537 debugstr_a(info
->Algorithm
.pszObjId
));
538 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
539 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
544 SetLastError(STATUS_ACCESS_VIOLATION
);
551 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
552 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
553 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
559 const CERT_SIGNED_CONTENT_INFO
*info
=
560 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
561 struct AsnEncodeSequenceItem items
[] = {
562 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
563 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
564 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
567 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
568 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
569 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
570 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
575 SetLastError(STATUS_ACCESS_VIOLATION
);
582 /* Like in Windows, this blithely ignores the validity of the passed-in
583 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
584 * decode properly, see CRYPT_AsnDecodeCertInfo.
586 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
587 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
588 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
594 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
595 struct AsnEncodeSequenceItem items
[10] = {
596 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
597 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
598 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
599 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
600 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
601 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
602 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
605 struct AsnConstructedItem constructed
[3] = { { 0 } };
606 DWORD cItem
= 7, cConstructed
= 0;
608 if (info
->IssuerUniqueId
.cbData
)
610 constructed
[cConstructed
].tag
= 1;
611 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
612 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
613 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
614 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
618 if (info
->SubjectUniqueId
.cbData
)
620 constructed
[cConstructed
].tag
= 2;
621 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
622 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
623 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
624 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
628 if (info
->cExtension
)
630 constructed
[cConstructed
].tag
= 3;
631 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
632 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
633 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
634 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
639 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
640 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
644 SetLastError(STATUS_ACCESS_VIOLATION
);
651 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
652 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
654 struct AsnEncodeSequenceItem items
[3] = {
655 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
656 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
662 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
664 if (entry
->cExtension
)
666 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
667 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
671 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
672 pbEncoded
, pcbEncoded
);
674 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
678 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
679 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
680 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
682 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
683 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
684 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
685 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
688 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
692 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
696 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
697 bytesNeeded
= 1 + lenBytes
+ dataLen
;
699 *pcbEncoded
= bytesNeeded
;
702 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
703 pcbEncoded
, bytesNeeded
)))
705 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
706 pbEncoded
= *(BYTE
**)pbEncoded
;
707 *pbEncoded
++ = ASN_SEQUENCEOF
;
708 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
709 pbEncoded
+= lenBytes
;
710 for (i
= 0; i
< cCRLEntry
; i
++)
712 DWORD size
= dataLen
;
714 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
723 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
724 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
725 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
727 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
730 /* CRL_V1 is not encoded */
737 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
738 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
742 /* Like in Windows, this blithely ignores the validity of the passed-in
743 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
744 * decode properly, see CRYPT_AsnDecodeCRLInfo.
746 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
747 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
748 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
754 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
755 struct AsnEncodeSequenceItem items
[7] = {
756 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
757 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
758 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
759 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
764 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
766 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
767 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
772 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
773 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
776 if (info
->cExtension
)
778 items
[cItem
].pvStructInfo
= &info
->cExtension
;
779 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
783 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
784 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
788 SetLastError(STATUS_ACCESS_VIOLATION
);
795 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
799 struct AsnEncodeSequenceItem items
[3] = {
800 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
806 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
810 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
811 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
814 items
[cItem
].pvStructInfo
= &ext
->Value
;
815 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
818 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
819 pbEncoded
, pcbEncoded
);
820 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
824 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
825 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
826 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
832 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
833 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
836 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
840 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
844 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
845 bytesNeeded
= 1 + lenBytes
+ dataLen
;
847 *pcbEncoded
= bytesNeeded
;
850 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
851 pcbEncoded
, bytesNeeded
)))
853 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
854 pbEncoded
= *(BYTE
**)pbEncoded
;
855 *pbEncoded
++ = ASN_SEQUENCEOF
;
856 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
857 pbEncoded
+= lenBytes
;
858 for (i
= 0; i
< exts
->cExtension
; i
++)
860 DWORD size
= dataLen
;
862 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
872 SetLastError(STATUS_ACCESS_VIOLATION
);
879 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
880 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
881 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
883 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
884 DWORD bytesNeeded
= 0, lenBytes
;
889 TRACE("%s\n", debugstr_a(pszObjId
));
896 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
898 SetLastError(CRYPT_E_ASN1_ERROR
);
902 firstByte
= val1
* 40 + val2
;
903 ptr
= pszObjId
+ firstPos
;
908 /* note I assume each component is at most 32-bits long in base 2 */
909 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
911 if (val1
>= 0x10000000)
913 else if (val1
>= 0x200000)
915 else if (val1
>= 0x4000)
917 else if (val1
>= 0x80)
927 SetLastError(CRYPT_E_ASN1_ERROR
);
931 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
935 bytesNeeded
+= 1 + lenBytes
;
938 if (*pcbEncoded
< bytesNeeded
)
940 SetLastError(ERROR_MORE_DATA
);
945 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
946 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
947 pbEncoded
+= lenBytes
;
953 *pbEncoded
++ = firstByte
;
954 ptr
= pszObjId
+ firstPos
;
957 sscanf(ptr
, "%d%n", &val
, &pos
);
959 unsigned char outBytes
[5];
962 if (val
>= 0x10000000)
964 else if (val
>= 0x200000)
966 else if (val
>= 0x4000)
968 else if (val
>= 0x80)
972 for (i
= numBytes
; i
> 0; i
--)
974 outBytes
[i
- 1] = val
& 0x7f;
977 for (i
= 0; i
< numBytes
- 1; i
++)
978 *pbEncoded
++ = outBytes
[i
] | 0x80;
979 *pbEncoded
++ = outBytes
[i
];
988 *pcbEncoded
= bytesNeeded
;
992 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
993 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
996 DWORD bytesNeeded
, lenBytes
, encodedLen
;
999 switch (value
->dwValueType
)
1001 case CERT_RDN_NUMERIC_STRING
:
1002 tag
= ASN_NUMERICSTRING
;
1003 encodedLen
= value
->Value
.cbData
;
1005 case CERT_RDN_PRINTABLE_STRING
:
1006 tag
= ASN_PRINTABLESTRING
;
1007 encodedLen
= value
->Value
.cbData
;
1009 case CERT_RDN_IA5_STRING
:
1010 tag
= ASN_IA5STRING
;
1011 encodedLen
= value
->Value
.cbData
;
1013 case CERT_RDN_ANY_TYPE
:
1014 /* explicitly disallowed */
1015 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1018 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
1021 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1022 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1025 if (*pcbEncoded
< bytesNeeded
)
1027 SetLastError(ERROR_MORE_DATA
);
1033 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1034 pbEncoded
+= lenBytes
;
1035 switch (value
->dwValueType
)
1037 case CERT_RDN_NUMERIC_STRING
:
1038 case CERT_RDN_PRINTABLE_STRING
:
1039 case CERT_RDN_IA5_STRING
:
1040 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1044 *pcbEncoded
= bytesNeeded
;
1048 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1049 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1051 DWORD bytesNeeded
= 0, lenBytes
, size
;
1054 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1055 0, NULL
, NULL
, &size
);
1058 bytesNeeded
+= size
;
1059 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1060 * with dwValueType, so "cast" it to get its encoded size
1062 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1063 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1066 bytesNeeded
+= size
;
1067 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1068 bytesNeeded
+= 1 + lenBytes
;
1071 if (*pcbEncoded
< bytesNeeded
)
1073 SetLastError(ERROR_MORE_DATA
);
1078 *pbEncoded
++ = ASN_SEQUENCE
;
1079 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1081 pbEncoded
+= lenBytes
;
1082 size
= bytesNeeded
- 1 - lenBytes
;
1083 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1084 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1088 size
= bytesNeeded
- 1 - lenBytes
- size
;
1089 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1090 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1095 *pcbEncoded
= bytesNeeded
;
1101 static int BLOBComp(const void *l
, const void *r
)
1103 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1106 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1107 ret
= a
->cbData
- b
->cbData
;
1111 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1113 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1114 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1117 CRYPT_DER_BLOB
*blobs
= NULL
;
1121 DWORD bytesNeeded
= 0, lenBytes
, i
;
1127 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1131 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1133 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1135 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1136 NULL
, &blobs
[i
].cbData
);
1138 bytesNeeded
+= blobs
[i
].cbData
;
1142 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1143 bytesNeeded
+= 1 + lenBytes
;
1146 if (*pcbEncoded
< bytesNeeded
)
1148 SetLastError(ERROR_MORE_DATA
);
1153 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1155 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1156 if (!blobs
[i
].pbData
)
1159 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1160 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1165 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1167 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1168 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1170 pbEncoded
+= lenBytes
;
1171 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1173 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1174 pbEncoded
+= blobs
[i
].cbData
;
1179 *pcbEncoded
= bytesNeeded
;
1183 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1184 CryptMemFree(blobs
[i
].pbData
);
1189 SetLastError(STATUS_ACCESS_VIOLATION
);
1193 CryptMemFree(blobs
);
1197 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1198 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1199 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1205 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1206 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1208 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1210 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1212 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1215 bytesNeeded
+= size
;
1217 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1218 bytesNeeded
+= 1 + lenBytes
;
1222 *pcbEncoded
= bytesNeeded
;
1225 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1226 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1228 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1229 pbEncoded
= *(BYTE
**)pbEncoded
;
1230 *pbEncoded
++ = ASN_SEQUENCEOF
;
1231 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1233 pbEncoded
+= lenBytes
;
1234 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1237 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1238 &info
->rgRDN
[i
], pbEncoded
, &size
);
1242 bytesNeeded
-= size
;
1251 SetLastError(STATUS_ACCESS_VIOLATION
);
1258 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1259 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1260 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1262 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1271 else if (*pcbEncoded
< 3)
1274 SetLastError(ERROR_MORE_DATA
);
1280 *pbEncoded
++ = ASN_BOOL
;
1282 *pbEncoded
++ = val
? 0xff : 0;
1285 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1289 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1290 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1296 switch (entry
->dwAltNameChoice
)
1298 case CERT_ALT_NAME_RFC822_NAME
:
1299 case CERT_ALT_NAME_DNS_NAME
:
1300 case CERT_ALT_NAME_URL
:
1301 if (entry
->u
.pwszURL
)
1305 /* Not + 1: don't encode the NULL-terminator */
1306 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1307 for (i
= 0; ret
&& i
< dataLen
; i
++)
1309 if (entry
->u
.pwszURL
[i
] > 0x7f)
1311 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1320 case CERT_ALT_NAME_IP_ADDRESS
:
1321 dataLen
= entry
->u
.IPAddress
.cbData
;
1323 case CERT_ALT_NAME_REGISTERED_ID
:
1324 /* FIXME: encode OID */
1325 case CERT_ALT_NAME_OTHER_NAME
:
1326 case CERT_ALT_NAME_DIRECTORY_NAME
:
1327 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1330 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1335 DWORD bytesNeeded
, lenBytes
;
1337 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1338 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1340 *pcbEncoded
= bytesNeeded
;
1341 else if (*pcbEncoded
< bytesNeeded
)
1343 SetLastError(ERROR_MORE_DATA
);
1344 *pcbEncoded
= bytesNeeded
;
1349 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1350 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1351 pbEncoded
+= lenBytes
;
1352 switch (entry
->dwAltNameChoice
)
1354 case CERT_ALT_NAME_RFC822_NAME
:
1355 case CERT_ALT_NAME_DNS_NAME
:
1356 case CERT_ALT_NAME_URL
:
1360 for (i
= 0; i
< dataLen
; i
++)
1361 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1364 case CERT_ALT_NAME_IP_ADDRESS
:
1365 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1369 *pcbEncoded
= bytesNeeded
;
1372 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1376 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1377 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1378 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1384 const CERT_ALT_NAME_INFO
*info
=
1385 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1386 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1389 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1390 * can't encode an erroneous entry index if it's bigger than this.
1392 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1396 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1400 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1402 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1403 * the bad character, now set the index of the bad
1406 *pcbEncoded
= (BYTE
)i
<<
1407 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1412 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1413 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1416 *pcbEncoded
= bytesNeeded
;
1421 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1422 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1424 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1425 pbEncoded
= *(BYTE
**)pbEncoded
;
1426 *pbEncoded
++ = ASN_SEQUENCEOF
;
1427 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1428 pbEncoded
+= lenBytes
;
1429 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1431 DWORD len
= dataLen
;
1433 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1447 SetLastError(STATUS_ACCESS_VIOLATION
);
1454 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
1455 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1456 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1462 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
1463 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
1464 struct AsnEncodeSequenceItem items
[3] = {
1465 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
1470 if (info
->fPathLenConstraint
)
1472 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1473 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1476 if (info
->cSubtreesConstraint
)
1478 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
1479 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
1482 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1483 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1487 SetLastError(STATUS_ACCESS_VIOLATION
);
1494 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1495 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1496 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1502 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1503 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1504 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1509 items
[cItem
].pvStructInfo
= &info
->fCA
;
1510 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1513 if (info
->fPathLenConstraint
)
1515 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1516 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1519 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1520 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1524 SetLastError(STATUS_ACCESS_VIOLATION
);
1531 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1532 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1533 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1539 const BLOBHEADER
*hdr
=
1540 (const BLOBHEADER
*)pvStructInfo
;
1542 if (hdr
->bType
!= PUBLICKEYBLOB
)
1544 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
1549 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1550 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1551 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1552 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1553 struct AsnEncodeSequenceItem items
[] = {
1554 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1555 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1558 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1559 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1565 SetLastError(STATUS_ACCESS_VIOLATION
);
1572 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1573 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1574 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1580 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1581 DWORD bytesNeeded
, lenBytes
;
1583 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1584 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1586 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1587 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1590 *pcbEncoded
= bytesNeeded
;
1595 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1596 pcbEncoded
, bytesNeeded
)))
1598 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1599 pbEncoded
= *(BYTE
**)pbEncoded
;
1600 *pbEncoded
++ = ASN_OCTETSTRING
;
1601 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1602 pbEncoded
+= lenBytes
;
1604 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1610 SetLastError(STATUS_ACCESS_VIOLATION
);
1614 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1618 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1619 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1620 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1626 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1627 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1630 /* yep, MS allows cUnusedBits to be >= 8 */
1631 if (!blob
->cUnusedBits
)
1633 dataBytes
= blob
->cbData
;
1636 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1638 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1639 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1647 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1648 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1651 *pcbEncoded
= bytesNeeded
;
1656 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1657 pcbEncoded
, bytesNeeded
)))
1659 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1660 pbEncoded
= *(BYTE
**)pbEncoded
;
1661 *pbEncoded
++ = ASN_BITSTRING
;
1662 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1663 pbEncoded
+= lenBytes
;
1664 *pbEncoded
++ = unusedBits
;
1667 BYTE mask
= 0xff << unusedBits
;
1671 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1672 pbEncoded
+= dataBytes
- 1;
1674 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1681 SetLastError(STATUS_ACCESS_VIOLATION
);
1688 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1689 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1690 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1696 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1697 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1702 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
1707 for (i
= 0; i
< newBlob
.cbData
; i
++)
1708 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1714 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1715 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1716 CryptMemFree(newBlob
.pbData
);
1720 SetLastError(STATUS_ACCESS_VIOLATION
);
1727 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1728 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1729 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1731 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1733 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1734 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1737 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1738 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1739 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1745 DWORD significantBytes
, lenBytes
;
1746 BYTE padByte
= 0, bytesNeeded
;
1748 const CRYPT_INTEGER_BLOB
*blob
=
1749 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1751 significantBytes
= blob
->cbData
;
1752 if (significantBytes
)
1754 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1756 /* negative, lop off leading (little-endian) 0xffs */
1757 for (; significantBytes
> 0 &&
1758 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1760 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1768 /* positive, lop off leading (little-endian) zeroes */
1769 for (; significantBytes
> 0 &&
1770 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1772 if (significantBytes
== 0)
1773 significantBytes
= 1;
1774 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1782 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1784 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1785 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1790 *pcbEncoded
= bytesNeeded
;
1795 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1796 pcbEncoded
, bytesNeeded
)))
1798 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1799 pbEncoded
= *(BYTE
**)pbEncoded
;
1800 *pbEncoded
++ = ASN_INTEGER
;
1803 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1804 pbEncoded
+= lenBytes
;
1805 *pbEncoded
++ = padByte
;
1809 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1810 pbEncoded
+= lenBytes
;
1812 for (; significantBytes
> 0; significantBytes
--)
1813 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1819 SetLastError(STATUS_ACCESS_VIOLATION
);
1826 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1827 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1828 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1834 DWORD significantBytes
, lenBytes
;
1837 const CRYPT_INTEGER_BLOB
*blob
=
1838 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1840 significantBytes
= blob
->cbData
;
1841 if (significantBytes
)
1843 /* positive, lop off leading (little-endian) zeroes */
1844 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
1847 if (significantBytes
== 0)
1848 significantBytes
= 1;
1849 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1853 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1855 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1856 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1861 *pcbEncoded
= bytesNeeded
;
1866 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1867 pcbEncoded
, bytesNeeded
)))
1869 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1870 pbEncoded
= *(BYTE
**)pbEncoded
;
1871 *pbEncoded
++ = ASN_INTEGER
;
1874 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1875 pbEncoded
+= lenBytes
;
1880 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1881 pbEncoded
+= lenBytes
;
1883 for (; significantBytes
> 0; significantBytes
--)
1884 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1890 SetLastError(STATUS_ACCESS_VIOLATION
);
1897 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
1898 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1899 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1901 CRYPT_INTEGER_BLOB blob
;
1904 /* Encode as an unsigned integer, then change the tag to enumerated */
1905 blob
.cbData
= sizeof(DWORD
);
1906 blob
.pbData
= (BYTE
*)pvStructInfo
;
1907 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
1908 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1909 if (ret
&& pbEncoded
)
1911 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1912 pbEncoded
= *(BYTE
**)pbEncoded
;
1913 pbEncoded
[0] = ASN_ENUMERATED
;
1918 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
1919 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1920 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1927 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1928 * temporary buffer because the output buffer is not NULL-terminated.
1931 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1935 *pcbEncoded
= bytesNeeded
;
1940 /* Sanity check the year, this is a two-digit year format */
1941 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1943 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
1945 SetLastError(CRYPT_E_BAD_ENCODE
);
1950 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1951 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1953 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1954 pbEncoded
= *(BYTE
**)pbEncoded
;
1955 buf
[0] = ASN_UTCTIME
;
1956 buf
[1] = bytesNeeded
- 2;
1957 snprintf(buf
+ 2, sizeof(buf
) - 2,
1958 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
1959 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
1960 sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
1961 sysTime
.wMinute
, sysTime
.wSecond
);
1962 memcpy(pbEncoded
, buf
, bytesNeeded
);
1969 SetLastError(STATUS_ACCESS_VIOLATION
);
1976 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
1977 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1978 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1985 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1986 * temporary buffer because the output buffer is not NULL-terminated.
1989 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1993 *pcbEncoded
= bytesNeeded
;
1998 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
2001 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2002 pcbEncoded
, bytesNeeded
);
2005 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2006 pbEncoded
= *(BYTE
**)pbEncoded
;
2007 buf
[0] = ASN_GENERALTIME
;
2008 buf
[1] = bytesNeeded
- 2;
2009 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2010 sysTime
.wYear
, sysTime
.wDay
, sysTime
.wMonth
, sysTime
.wHour
,
2011 sysTime
.wMinute
, sysTime
.wSecond
);
2012 memcpy(pbEncoded
, buf
, bytesNeeded
);
2018 SetLastError(STATUS_ACCESS_VIOLATION
);
2025 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2026 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2027 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2035 /* Check the year, if it's in the UTCTime range call that encode func */
2036 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2038 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2039 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2040 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2042 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2043 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2048 SetLastError(STATUS_ACCESS_VIOLATION
);
2055 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2056 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2057 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2063 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2064 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2065 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2067 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2068 dataLen
+= seq
->rgValue
[i
].cbData
;
2069 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2070 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2073 *pcbEncoded
= bytesNeeded
;
2078 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2079 pcbEncoded
, bytesNeeded
)))
2081 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2082 pbEncoded
= *(BYTE
**)pbEncoded
;
2083 *pbEncoded
++ = ASN_SEQUENCEOF
;
2084 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2085 pbEncoded
+= lenBytes
;
2086 for (i
= 0; i
< seq
->cValue
; i
++)
2088 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2089 seq
->rgValue
[i
].cbData
);
2090 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2097 SetLastError(STATUS_ACCESS_VIOLATION
);
2104 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2105 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2108 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2109 struct AsnConstructedItem constructed
= { 0 };
2110 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2111 DWORD cItem
= 0, cSwapped
= 0;
2113 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2115 case CRL_DIST_POINT_NO_NAME
:
2118 case CRL_DIST_POINT_FULL_NAME
:
2119 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2120 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2121 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2122 constructed
.tag
= 0;
2123 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2124 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2125 items
[cItem
].pvStructInfo
= &constructed
;
2126 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2130 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2131 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2137 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2139 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2140 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2141 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2142 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2143 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2147 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2149 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2150 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2151 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2152 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2153 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2158 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2159 pbEncoded
, pcbEncoded
);
2163 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2164 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2165 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2171 const CRL_DIST_POINTS_INFO
*info
=
2172 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2174 if (!info
->cDistPoint
)
2176 SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
));
2181 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2184 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2188 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2192 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2194 /* Have to propagate index of failing character */
2200 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2201 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2204 *pcbEncoded
= bytesNeeded
;
2209 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2210 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2212 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2213 pbEncoded
= *(BYTE
**)pbEncoded
;
2214 *pbEncoded
++ = ASN_SEQUENCEOF
;
2215 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2216 pbEncoded
+= lenBytes
;
2217 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2219 DWORD len
= dataLen
;
2221 ret
= CRYPT_AsnEncodeDistPoint(
2222 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
2236 SetLastError(STATUS_ACCESS_VIOLATION
);
2243 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
2244 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2245 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2251 const CERT_ENHKEY_USAGE
*usage
=
2252 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
2253 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2256 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2258 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2259 usage
->rgpszUsageIdentifier
[i
],
2260 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2262 bytesNeeded
+= size
;
2264 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2265 bytesNeeded
+= 1 + lenBytes
;
2269 *pcbEncoded
= bytesNeeded
;
2272 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2273 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2275 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2276 pbEncoded
= *(BYTE
**)pbEncoded
;
2277 *pbEncoded
++ = ASN_SEQUENCEOF
;
2278 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2280 pbEncoded
+= lenBytes
;
2281 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2284 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2285 usage
->rgpszUsageIdentifier
[i
],
2286 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2291 bytesNeeded
-= size
;
2300 SetLastError(STATUS_ACCESS_VIOLATION
);
2307 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2308 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2309 void *pvEncoded
, DWORD
*pcbEncoded
)
2311 static HCRYPTOIDFUNCSET set
= NULL
;
2313 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2314 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2316 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2317 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2318 pvEncoded
, pcbEncoded
);
2320 if (!pvEncoded
&& !pcbEncoded
)
2322 SetLastError(ERROR_INVALID_PARAMETER
);
2325 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2326 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2328 SetLastError(ERROR_FILE_NOT_FOUND
);
2332 SetLastError(NOERROR
);
2333 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2334 *(BYTE
**)pvEncoded
= NULL
;
2335 if (!HIWORD(lpszStructType
))
2337 switch (LOWORD(lpszStructType
))
2339 case (WORD
)X509_CERT
:
2340 encodeFunc
= CRYPT_AsnEncodeCert
;
2342 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2343 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2345 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2346 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2348 case (WORD
)X509_EXTENSIONS
:
2349 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2351 case (WORD
)X509_NAME
:
2352 encodeFunc
= CRYPT_AsnEncodeName
;
2354 case (WORD
)X509_PUBLIC_KEY_INFO
:
2355 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2357 case (WORD
)X509_ALTERNATE_NAME
:
2358 encodeFunc
= CRYPT_AsnEncodeAltName
;
2360 case (WORD
)X509_BASIC_CONSTRAINTS
:
2361 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2363 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2364 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2366 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2367 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2369 case (WORD
)X509_OCTET_STRING
:
2370 encodeFunc
= CRYPT_AsnEncodeOctets
;
2372 case (WORD
)X509_BITS
:
2373 case (WORD
)X509_KEY_USAGE
:
2374 encodeFunc
= CRYPT_AsnEncodeBits
;
2376 case (WORD
)X509_INTEGER
:
2377 encodeFunc
= CRYPT_AsnEncodeInt
;
2379 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2380 encodeFunc
= CRYPT_AsnEncodeInteger
;
2382 case (WORD
)X509_MULTI_BYTE_UINT
:
2383 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2385 case (WORD
)X509_ENUMERATED
:
2386 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2388 case (WORD
)X509_CHOICE_OF_TIME
:
2389 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2391 case (WORD
)X509_SEQUENCE_OF_ANY
:
2392 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2394 case (WORD
)PKCS_UTC_TIME
:
2395 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2397 case (WORD
)X509_CRL_DIST_POINTS
:
2398 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2400 case (WORD
)X509_ENHANCED_KEY_USAGE
:
2401 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2404 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2407 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2408 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2409 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2410 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2411 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2412 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2413 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2414 encodeFunc
= CRYPT_AsnEncodeBits
;
2415 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2416 encodeFunc
= CRYPT_AsnEncodeOctets
;
2417 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
2418 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2419 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2420 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2421 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2422 encodeFunc
= CRYPT_AsnEncodeAltName
;
2423 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2424 encodeFunc
= CRYPT_AsnEncodeAltName
;
2425 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2426 encodeFunc
= CRYPT_AsnEncodeAltName
;
2427 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2428 encodeFunc
= CRYPT_AsnEncodeAltName
;
2429 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2430 encodeFunc
= CRYPT_AsnEncodeAltName
;
2431 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2432 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2433 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2434 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2436 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2437 debugstr_a(lpszStructType
));
2441 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
2442 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2443 (void **)&encodeFunc
, &hFunc
);
2446 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2447 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2449 SetLastError(ERROR_FILE_NOT_FOUND
);
2451 CryptFreeOIDFunctionAddress(hFunc
, 0);
2455 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2456 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2457 DWORD
*pcbStructInfo
)
2459 static HCRYPTOIDFUNCSET set
= NULL
;
2461 CryptDecodeObjectFunc pCryptDecodeObject
;
2462 HCRYPTOIDFUNCADDR hFunc
;
2464 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2465 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2466 pvStructInfo
, pcbStructInfo
);
2468 if (!pvStructInfo
&& !pcbStructInfo
)
2470 SetLastError(ERROR_INVALID_PARAMETER
);
2474 /* Try registered DLL first.. */
2476 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
2477 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2478 (void **)&pCryptDecodeObject
, &hFunc
);
2479 if (pCryptDecodeObject
)
2481 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2482 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2483 CryptFreeOIDFunctionAddress(hFunc
, 0);
2487 /* If not, use CryptDecodeObjectEx */
2488 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2489 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2494 /* Gets the number of length bytes from the given (leading) length byte */
2495 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2497 /* Helper function to get the encoded length of the data starting at pbEncoded,
2498 * where pbEncoded[0] is the tag. If the data are too short to contain a
2499 * length or if the length is too large for cbEncoded, sets an appropriate
2500 * error code and returns FALSE.
2502 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2509 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2512 else if (pbEncoded
[1] <= 0x7f)
2514 if (pbEncoded
[1] + 1 > cbEncoded
)
2516 SetLastError(CRYPT_E_ASN1_EOD
);
2521 *len
= pbEncoded
[1];
2527 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2529 if (lenLen
> sizeof(DWORD
) + 1)
2531 SetLastError(CRYPT_E_ASN1_LARGE
);
2534 else if (lenLen
+ 2 > cbEncoded
)
2536 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2547 out
|= *pbEncoded
++;
2549 if (out
+ lenLen
+ 1 > cbEncoded
)
2551 SetLastError(CRYPT_E_ASN1_EOD
);
2564 /* Helper function to check *pcbStructInfo, set it to the required size, and
2565 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2566 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2567 * pointer to the newly allocated memory.
2569 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2570 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2575 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2577 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2578 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2580 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2581 if (!*(BYTE
**)pvStructInfo
)
2584 *pcbStructInfo
= bytesNeeded
;
2586 else if (*pcbStructInfo
< bytesNeeded
)
2588 *pcbStructInfo
= bytesNeeded
;
2589 SetLastError(ERROR_MORE_DATA
);
2596 * The expected tag of the item. If tag is 0, decodeFunc is called
2597 * regardless of the tag value seen.
2599 * A sequence is decoded into a struct. The offset member is the
2600 * offset of this item within that struct.
2602 * The decoder function to use. If this is NULL, then the member isn't
2603 * decoded, but minSize space is reserved for it.
2605 * The minimum amount of space occupied after decoding. You must set this.
2607 * If true, and the tag doesn't match the expected tag for this item,
2608 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
2609 * filled with 0 for this member.
2610 * hasPointer, pointerOffset, minSize:
2611 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2612 * the offset within the (outer) struct of the data pointer (or to the
2613 * first data pointer, if more than one exist).
2615 * Used by CRYPT_AsnDecodeSequence, not for your use.
2617 struct AsnDecodeSequenceItem
2621 CryptDecodeObjectExFunc decodeFunc
;
2625 DWORD pointerOffset
;
2629 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
2630 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2631 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
)
2637 ptr
= pbEncoded
+ 1 + GET_LEN_BYTES(pbEncoded
[1]);
2638 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
2640 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2644 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2647 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2649 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
2651 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
2653 TRACE("Setting next pointer to %p\n",
2655 *(BYTE
**)((BYTE
*)pvStructInfo
+
2656 items
[i
].pointerOffset
) = nextData
;
2658 if (items
[i
].decodeFunc
)
2661 TRACE("decoding item %ld\n", i
);
2663 TRACE("sizing item %ld\n", i
);
2664 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2665 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2666 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2667 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
2668 : NULL
, &items
[i
].size
);
2671 if (nextData
&& items
[i
].hasPointer
&&
2672 items
[i
].size
> items
[i
].minSize
)
2674 nextData
+= items
[i
].size
- items
[i
].minSize
;
2675 /* align nextData to DWORD boundaries */
2676 if (items
[i
].size
% sizeof(DWORD
))
2677 nextData
+= sizeof(DWORD
) - items
[i
].size
%
2680 /* Account for alignment padding */
2681 if (items
[i
].size
% sizeof(DWORD
))
2682 items
[i
].size
+= sizeof(DWORD
) -
2683 items
[i
].size
% sizeof(DWORD
);
2684 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2686 else if (items
[i
].optional
&&
2687 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2689 TRACE("skipping optional item %ld\n", i
);
2690 items
[i
].size
= items
[i
].minSize
;
2691 SetLastError(NOERROR
);
2695 TRACE("item %ld failed: %08lx\n", i
,
2699 items
[i
].size
= items
[i
].minSize
;
2701 else if (items
[i
].optional
)
2703 TRACE("skipping optional item %ld\n", i
);
2704 items
[i
].size
= items
[i
].minSize
;
2708 TRACE("tag %02x doesn't match expected %02x\n",
2709 ptr
[0], items
[i
].tag
);
2710 SetLastError(CRYPT_E_ASN1_BADTAG
);
2715 else if (items
[i
].optional
)
2717 TRACE("missing optional item %ld, skipping\n", i
);
2718 items
[i
].size
= items
[i
].minSize
;
2722 TRACE("not enough bytes for item %ld, failing\n", i
);
2723 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2727 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2729 TRACE("%ld remaining bytes, failing\n", cbEncoded
-
2731 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2737 /* This decodes an arbitrary sequence into a contiguous block of memory
2738 * (basically, a struct.) Each element being decoded is described by a struct
2739 * AsnDecodeSequenceItem, see above.
2740 * startingPointer is an optional pointer to the first place where dynamic
2741 * data will be stored. If you know the starting offset, you may pass it
2742 * here. Otherwise, pass NULL, and one will be inferred from the items.
2743 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2744 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2746 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2747 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2748 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2749 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2753 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
2754 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2757 if (pbEncoded
[0] == ASN_SEQUENCE
)
2761 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2765 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, pbEncoded
,
2766 cbEncoded
, dwFlags
, NULL
, NULL
);
2769 DWORD bytesNeeded
= 0, structSize
= 0;
2771 for (i
= 0; i
< cItem
; i
++)
2773 bytesNeeded
+= items
[i
].size
;
2774 structSize
+= items
[i
].minSize
;
2777 *pcbStructInfo
= bytesNeeded
;
2778 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2779 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2783 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2784 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2785 if (startingPointer
)
2786 nextData
= (BYTE
*)startingPointer
;
2788 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
2789 memset(pvStructInfo
, 0, structSize
);
2790 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
2791 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
);
2798 SetLastError(CRYPT_E_ASN1_BADTAG
);
2801 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2806 * The expected tag of the entire encoded array (usually a variant
2807 * of ASN_SETOF or ASN_SEQUENCEOF.)
2809 * used to decode each item in the array
2811 * is the minimum size of each decoded item
2813 * indicates whether each item has a dynamic pointer
2815 * indicates the offset within itemSize at which the pointer exists
2817 struct AsnArrayDescriptor
2820 CryptDecodeObjectExFunc decodeFunc
;
2823 DWORD pointerOffset
;
2826 struct AsnArrayItemSize
2832 /* Decodes an array of like types into a struct GenericArray.
2833 * The layout and decoding of the array are described by a struct
2834 * AsnArrayDescriptor.
2836 static BOOL
CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor
*arrayDesc
,
2837 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2838 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2839 void *startingPointer
)
2843 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc
, pbEncoded
,
2844 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2847 if (pbEncoded
[0] == arrayDesc
->tag
)
2851 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2853 DWORD bytesNeeded
, cItems
= 0;
2854 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2855 /* There can be arbitrarily many items, but there is often only one.
2857 struct AsnArrayItemSize itemSize
= { 0 }, *itemSizes
= &itemSize
;
2859 bytesNeeded
= sizeof(struct GenericArray
);
2864 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2865 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
2867 DWORD itemLenBytes
, itemDataLen
, size
;
2869 itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2870 /* Each item decoded may not tolerate extraneous bytes, so
2871 * get the length of the next element and pass it directly.
2873 ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2876 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
2877 1 + itemLenBytes
+ itemDataLen
,
2878 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2885 if (itemSizes
!= &itemSize
)
2886 itemSizes
= CryptMemRealloc(itemSizes
,
2887 cItems
* sizeof(struct AsnArrayItemSize
));
2892 cItems
* sizeof(struct AsnArrayItemSize
));
2893 memcpy(itemSizes
, &itemSize
, sizeof(itemSize
));
2897 itemSizes
[cItems
- 1].encodedLen
= 1 + itemLenBytes
2899 itemSizes
[cItems
- 1].size
= size
;
2900 bytesNeeded
+= size
;
2901 ret
= CRYPT_GetLen(ptr
,
2902 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2904 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2914 *pcbStructInfo
= bytesNeeded
;
2915 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2916 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2921 struct GenericArray
*array
;
2923 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2924 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2925 array
= (struct GenericArray
*)pvStructInfo
;
2926 array
->cItems
= cItems
;
2927 if (startingPointer
)
2928 array
->rgItems
= startingPointer
;
2930 array
->rgItems
= (BYTE
*)array
+
2931 sizeof(struct GenericArray
);
2932 nextData
= (BYTE
*)array
->rgItems
+
2933 array
->cItems
* arrayDesc
->itemSize
;
2934 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2935 i
< cItems
&& ptr
- pbEncoded
- 1 - lenBytes
<
2938 if (arrayDesc
->hasPointer
)
2939 *(BYTE
**)(array
->rgItems
+ i
* arrayDesc
->itemSize
2940 + arrayDesc
->pointerOffset
) = nextData
;
2941 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
2942 itemSizes
[i
].encodedLen
,
2943 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2944 array
->rgItems
+ i
* arrayDesc
->itemSize
,
2945 &itemSizes
[i
].size
);
2950 nextData
+= itemSizes
[i
].size
- arrayDesc
->itemSize
;
2951 ret
= CRYPT_GetLen(ptr
,
2952 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2954 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2959 if (itemSizes
!= &itemSize
)
2960 CryptMemFree(itemSizes
);
2965 SetLastError(CRYPT_E_ASN1_BADTAG
);
2971 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2972 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2973 * to CRYPT_E_ASN1_CORRUPT.
2974 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2977 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2978 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2979 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2984 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2986 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2987 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2989 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2990 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2993 *pcbStructInfo
= bytesNeeded
;
2994 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2995 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2997 CRYPT_DER_BLOB
*blob
;
2999 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3000 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3001 blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
3002 blob
->cbData
= 1 + lenBytes
+ dataLen
;
3005 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3006 blob
->pbData
= (BYTE
*)pbEncoded
;
3009 assert(blob
->pbData
);
3010 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3015 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3023 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
3024 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
3025 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3026 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3030 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
3031 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3033 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3036 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
3037 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
3038 pvStructInfo
, pcbStructInfo
);
3039 if (ret
&& pvStructInfo
)
3041 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
3048 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
3050 temp
= blob
->pbData
[i
];
3051 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
3052 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
3056 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3060 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
3061 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3062 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3066 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3067 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3071 struct AsnDecodeSequenceItem items
[] = {
3072 { 0, offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
3073 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
3074 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
3075 { ASN_SEQUENCEOF
, offsetof(CERT_SIGNED_CONTENT_INFO
,
3076 SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
3077 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
,
3078 offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
3079 { ASN_BITSTRING
, offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
3080 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
3081 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
3084 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
3085 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
3086 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3087 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3088 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3092 SetLastError(STATUS_ACCESS_VIOLATION
);
3099 /* Internal function */
3100 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
3101 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3102 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3107 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3109 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3111 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
3112 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
3113 pvStructInfo
, pcbStructInfo
);
3118 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
3119 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3120 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3124 struct AsnDecodeSequenceItem items
[] = {
3125 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
3126 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3127 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
3128 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3131 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3132 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3133 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3137 /* Internal function */
3138 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
3139 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3140 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3145 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3147 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3149 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3150 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
3151 pDecodePara
, pvStructInfo
, pcbStructInfo
);
3156 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
3157 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3158 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3162 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3163 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3167 struct AsnDecodeSequenceItem items
[] = {
3168 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CERT_INFO
, dwVersion
),
3169 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3170 { ASN_INTEGER
, offsetof(CERT_INFO
, SerialNumber
),
3171 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
3172 TRUE
, offsetof(CERT_INFO
, SerialNumber
.pbData
), 0 },
3173 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SignatureAlgorithm
),
3174 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3175 FALSE
, TRUE
, offsetof(CERT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
3176 { 0, offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3177 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
3179 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, NotBefore
),
3180 CRYPT_AsnDecodeValidity
, sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
,
3182 { 0, offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
3183 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
3185 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SubjectPublicKeyInfo
),
3186 CRYPT_AsnDecodePubKeyInfoInternal
, sizeof(CERT_PUBLIC_KEY_INFO
),
3187 FALSE
, TRUE
, offsetof(CERT_INFO
,
3188 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
3189 { ASN_BITSTRING
, offsetof(CERT_INFO
, IssuerUniqueId
),
3190 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3191 offsetof(CERT_INFO
, IssuerUniqueId
.pbData
), 0 },
3192 { ASN_BITSTRING
, offsetof(CERT_INFO
, SubjectUniqueId
),
3193 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3194 offsetof(CERT_INFO
, SubjectUniqueId
.pbData
), 0 },
3195 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3, offsetof(CERT_INFO
, cExtension
),
3196 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
3197 offsetof(CERT_INFO
, rgExtension
), 0 },
3200 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3201 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3202 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3206 SetLastError(STATUS_ACCESS_VIOLATION
);
3213 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType
,
3214 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3215 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3218 struct AsnDecodeSequenceItem items
[] = {
3219 { ASN_INTEGER
, offsetof(CRL_ENTRY
, SerialNumber
),
3220 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
,
3221 offsetof(CRL_ENTRY
, SerialNumber
.pbData
), 0 },
3222 { 0, offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
3223 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3224 { ASN_SEQUENCEOF
, offsetof(CRL_ENTRY
, cExtension
),
3225 CRYPT_AsnDecodeExtensionsInternal
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
3226 offsetof(CRL_ENTRY
, rgExtension
), 0 },
3228 PCRL_ENTRY entry
= (PCRL_ENTRY
)pvStructInfo
;
3230 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
3233 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3234 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3235 NULL
, entry
, pcbStructInfo
, entry
? entry
->SerialNumber
.pbData
: NULL
);
3239 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
3240 * been set prior to calling.
3242 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
3243 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3244 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3247 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3248 CRYPT_AsnDecodeCRLEntry
, sizeof(CRL_ENTRY
), TRUE
,
3249 offsetof(CRL_ENTRY
, SerialNumber
.pbData
) };
3250 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
3252 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3253 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3255 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3256 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3257 entries
? entries
->rgItems
: NULL
);
3258 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3262 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
3263 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3264 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3268 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3269 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3273 struct AsnDecodeSequenceItem items
[] = {
3274 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CRL_INFO
, dwVersion
),
3275 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3276 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, SignatureAlgorithm
),
3277 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3278 FALSE
, TRUE
, offsetof(CRL_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
3279 { 0, offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3280 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3282 { 0, offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3283 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3284 { 0, offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3285 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
3286 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, cCRLEntry
),
3287 CRYPT_AsnDecodeCRLEntries
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3288 offsetof(CRL_INFO
, rgCRLEntry
), 0 },
3289 /* Note that the extensions are ignored by MS, so I'll ignore them too
3291 { 0, offsetof(CRL_INFO
, cExtension
), NULL
,
3292 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
3295 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3296 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3297 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3301 SetLastError(STATUS_ACCESS_VIOLATION
);
3306 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3310 /* Differences between this and CRYPT_AsnDecodeOid:
3311 * - pvStructInfo is a LPSTR *, not an LPSTR
3312 * - CRYPT_AsnDecodeOid doesn't account for the size of an LPSTR in its byte
3313 * count, whereas our callers (typically CRYPT_AsnDecodeSequence) expect this
3316 static BOOL WINAPI
CRYPT_AsnDecodeOidWrapper(DWORD dwCertEncodingType
,
3317 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3318 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3322 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3323 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3325 ret
= CRYPT_AsnDecodeOid(pbEncoded
, cbEncoded
, dwFlags
,
3326 pvStructInfo
? *(LPSTR
*)pvStructInfo
: NULL
, pcbStructInfo
);
3327 if (ret
|| GetLastError() == ERROR_MORE_DATA
)
3328 *pcbStructInfo
+= sizeof(LPSTR
);
3329 if (ret
&& pvStructInfo
)
3330 TRACE("returning %s\n", debugstr_a(*(LPSTR
*)pvStructInfo
));
3334 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
3337 static BOOL WINAPI
CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType
,
3338 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3339 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3341 struct AsnDecodeSequenceItem items
[] = {
3342 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_EXTENSION
, pszObjId
),
3343 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3344 offsetof(CERT_EXTENSION
, pszObjId
), 0 },
3345 { ASN_BOOL
, offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
3346 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
3347 { ASN_OCTETSTRING
, offsetof(CERT_EXTENSION
, Value
),
3348 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
,
3349 offsetof(CERT_EXTENSION
, Value
.pbData
) },
3352 PCERT_EXTENSION ext
= (PCERT_EXTENSION
)pvStructInfo
;
3354 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
3358 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
3359 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3360 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3361 ext
, pcbStructInfo
, ext
? ext
->pszObjId
: NULL
);
3363 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
3364 debugstr_a(ext
->pszObjId
));
3365 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3369 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
3370 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3371 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3374 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3375 CRYPT_AsnDecodeExtension
, sizeof(CERT_EXTENSION
), TRUE
,
3376 offsetof(CERT_EXTENSION
, pszObjId
) };
3377 PCERT_EXTENSIONS exts
= (PCERT_EXTENSIONS
)pvStructInfo
;
3379 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3380 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3382 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3383 pDecodePara
, pvStructInfo
, pcbStructInfo
, exts
? exts
->rgExtension
: NULL
);
3387 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3388 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3389 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3395 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3396 lpszStructType
, pbEncoded
, cbEncoded
,
3397 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3398 if (ret
&& pvStructInfo
)
3400 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3401 pcbStructInfo
, *pcbStructInfo
);
3404 CERT_EXTENSIONS
*exts
;
3406 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3407 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3408 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3409 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3410 sizeof(CERT_EXTENSIONS
));
3411 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3412 lpszStructType
, pbEncoded
, cbEncoded
,
3413 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3420 SetLastError(STATUS_ACCESS_VIOLATION
);
3427 /* FIXME: honor the CRYPT_DECODE_SHARE_OID_STRING_FLAG. */
3428 static BOOL WINAPI
CRYPT_AsnDecodeOid(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3429 DWORD dwFlags
, LPSTR pszObjId
, DWORD
*pcbObjId
)
3433 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, pszObjId
,
3438 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3442 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3444 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3449 /* The largest possible string for the first two components
3450 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3455 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3456 pbEncoded
[1 + lenBytes
] / 40,
3457 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3459 bytesNeeded
= strlen(firstTwo
) + 1;
3460 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3461 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3463 /* large enough for ".4000000" */
3467 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3474 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3477 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3484 snprintf(str
, sizeof(str
), ".%d", val
);
3485 bytesNeeded
+= strlen(str
);
3489 *pcbObjId
= bytesNeeded
;
3490 else if (*pcbObjId
< bytesNeeded
)
3492 *pcbObjId
= bytesNeeded
;
3493 SetLastError(ERROR_MORE_DATA
);
3499 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3500 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3502 pszObjId
+= strlen(pszObjId
);
3503 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3504 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3508 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3517 sprintf(pszObjId
, ".%d", val
);
3518 pszObjId
+= strlen(pszObjId
);
3524 *pcbObjId
= bytesNeeded
;
3529 SetLastError(CRYPT_E_ASN1_BADTAG
);
3535 SetLastError(STATUS_ACCESS_VIOLATION
);
3542 /* Warning: this assumes the address of value->Value.pbData is already set, in
3543 * order to avoid overwriting memory. (In some cases, it may change it, if it
3544 * doesn't copy anything to memory.) Be sure to set it correctly!
3546 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
3547 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3548 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3555 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
3557 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3559 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3561 switch (pbEncoded
[0])
3563 case ASN_NUMERICSTRING
:
3564 case ASN_PRINTABLESTRING
:
3568 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3569 SetLastError(OSS_UNIMPLEMENTED
);
3574 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3576 switch (pbEncoded
[0])
3578 case ASN_NUMERICSTRING
:
3579 case ASN_PRINTABLESTRING
:
3581 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3582 bytesNeeded
+= dataLen
;
3586 *pcbStructInfo
= bytesNeeded
;
3587 else if (*pcbStructInfo
< bytesNeeded
)
3589 *pcbStructInfo
= bytesNeeded
;
3590 SetLastError(ERROR_MORE_DATA
);
3595 *pcbStructInfo
= bytesNeeded
;
3596 switch (pbEncoded
[0])
3598 case ASN_NUMERICSTRING
:
3599 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3601 case ASN_PRINTABLESTRING
:
3602 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3605 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3610 switch (pbEncoded
[0])
3612 case ASN_NUMERICSTRING
:
3613 case ASN_PRINTABLESTRING
:
3615 value
->Value
.cbData
= dataLen
;
3616 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3617 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3621 assert(value
->Value
.pbData
);
3622 memcpy(value
->Value
.pbData
,
3623 pbEncoded
+ 1 + lenBytes
, dataLen
);
3630 value
->Value
.cbData
= 0;
3631 value
->Value
.pbData
= NULL
;
3639 SetLastError(STATUS_ACCESS_VIOLATION
);
3646 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType
,
3647 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3648 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3652 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3653 pvStructInfo
, *pcbStructInfo
);
3657 struct AsnDecodeSequenceItem items
[] = {
3658 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
3659 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3660 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
3661 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
), CRYPT_AsnDecodeNameValue
,
3662 sizeof(CERT_NAME_VALUE
), FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
,
3665 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
3668 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
3669 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3670 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3671 attr
, pcbStructInfo
, attr
? attr
->pszObjId
: NULL
);
3674 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
3675 debugstr_a(attr
->pszObjId
));
3676 TRACE("attr->dwValueType is %ld\n", attr
->dwValueType
);
3678 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3682 SetLastError(STATUS_ACCESS_VIOLATION
);
3689 static BOOL WINAPI
CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType
,
3690 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3691 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3697 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
3698 CRYPT_AsnDecodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
3699 offsetof(CERT_RDN_ATTR
, pszObjId
) };
3700 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
3702 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3703 pDecodePara
, pvStructInfo
, pcbStructInfo
, rdn
? rdn
->rgRDNAttr
: NULL
);
3707 SetLastError(STATUS_ACCESS_VIOLATION
);
3714 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3715 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3716 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3722 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3723 CRYPT_AsnDecodeRdn
, sizeof(CERT_RDN
), TRUE
,
3724 offsetof(CERT_RDN
, rgRDNAttr
) };
3726 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3727 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3731 SetLastError(STATUS_ACCESS_VIOLATION
);
3738 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
3739 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3740 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3743 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
3745 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3746 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3748 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3749 bytesNeeded
+= cbEncoded
;
3751 *pcbStructInfo
= bytesNeeded
;
3752 else if (*pcbStructInfo
< bytesNeeded
)
3754 SetLastError(ERROR_MORE_DATA
);
3755 *pcbStructInfo
= bytesNeeded
;
3760 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
3762 *pcbStructInfo
= bytesNeeded
;
3763 blob
->cbData
= cbEncoded
;
3764 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3765 blob
->pbData
= (LPBYTE
)pbEncoded
;
3768 assert(blob
->pbData
);
3769 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3775 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3776 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3777 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3779 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3780 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3782 struct AsnDecodeSequenceItem items
[] = {
3783 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
3784 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), FALSE
, TRUE
,
3785 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
3786 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
3787 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
3788 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
3791 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3792 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3794 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3795 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3796 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
3797 if (ret
&& pvStructInfo
)
3799 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
3800 debugstr_a(algo
->pszObjId
));
3805 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
3806 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3807 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3810 struct AsnDecodeSequenceItem items
[] = {
3811 { ASN_SEQUENCEOF
, offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
3812 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3813 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
3814 Algorithm
.pszObjId
) },
3815 { ASN_BITSTRING
, offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
3816 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
3817 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
3819 PCERT_PUBLIC_KEY_INFO info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
3821 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3822 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3823 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
?
3824 info
->Algorithm
.Parameters
.pbData
: NULL
);
3828 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
3829 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3830 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3838 if ((ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
3839 lpszStructType
, pbEncoded
, cbEncoded
,
3840 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
3843 *pcbStructInfo
= bytesNeeded
;
3844 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3845 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3847 PCERT_PUBLIC_KEY_INFO info
;
3849 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3850 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3851 info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
3852 info
->Algorithm
.Parameters
.pbData
= (BYTE
*)pvStructInfo
+
3853 sizeof(CERT_PUBLIC_KEY_INFO
);
3854 ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
3855 lpszStructType
, pbEncoded
, cbEncoded
,
3856 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3863 SetLastError(STATUS_ACCESS_VIOLATION
);
3870 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
3871 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3872 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3878 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3881 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
3883 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3886 if (pbEncoded
[1] > 1)
3888 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3893 *pcbStructInfo
= sizeof(BOOL
);
3896 else if (*pcbStructInfo
< sizeof(BOOL
))
3898 *pcbStructInfo
= sizeof(BOOL
);
3899 SetLastError(ERROR_MORE_DATA
);
3904 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
3907 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3911 static BOOL WINAPI
CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType
,
3912 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3913 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3915 PCERT_ALT_NAME_ENTRY entry
= (PCERT_ALT_NAME_ENTRY
)pvStructInfo
;
3916 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
3919 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3920 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3924 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3927 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
3929 SetLastError(CRYPT_E_ASN1_BADTAG
);
3932 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3933 if (1 + lenBytes
> cbEncoded
)
3935 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3938 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3940 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
3942 case 1: /* rfc822Name */
3943 case 2: /* dNSName */
3944 case 6: /* uniformResourceIdentifier */
3945 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
3947 case 7: /* iPAddress */
3948 bytesNeeded
+= dataLen
;
3950 case 8: /* registeredID */
3951 /* FIXME: decode as OID */
3952 case 0: /* otherName */
3953 case 4: /* directoryName */
3955 SetLastError(CRYPT_E_ASN1_BADTAG
);
3958 case 3: /* x400Address, unimplemented */
3959 case 5: /* ediPartyName, unimplemented */
3960 SetLastError(CRYPT_E_ASN1_BADTAG
);
3964 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3970 *pcbStructInfo
= bytesNeeded
;
3971 else if (*pcbStructInfo
< bytesNeeded
)
3973 *pcbStructInfo
= bytesNeeded
;
3974 SetLastError(ERROR_MORE_DATA
);
3979 *pcbStructInfo
= bytesNeeded
;
3980 /* MS used values one greater than the asn1 ones.. sigh */
3981 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
3982 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
3984 case 1: /* rfc822Name */
3985 case 2: /* dNSName */
3986 case 6: /* uniformResourceIdentifier */
3990 for (i
= 0; i
< dataLen
; i
++)
3991 entry
->u
.pwszURL
[i
] =
3992 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
3993 entry
->u
.pwszURL
[i
] = 0;
3994 TRACE("URL is %p (%s)\n", entry
->u
.pwszURL
,
3995 debugstr_w(entry
->u
.pwszURL
));
3998 case 7: /* iPAddress */
3999 /* The next data pointer is in the pwszURL spot, that is,
4000 * the first 4 bytes. Need to move it to the next spot.
4002 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
4003 entry
->u
.IPAddress
.cbData
= dataLen
;
4004 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
4014 static BOOL WINAPI
CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType
,
4015 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4016 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4019 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
4020 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
4021 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
4022 PCERT_ALT_NAME_INFO info
= (PCERT_ALT_NAME_INFO
)pvStructInfo
;
4024 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4025 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4028 TRACE("info->rgAltEntry is %p\n", info
->rgAltEntry
);
4029 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4030 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->rgAltEntry
: NULL
);
4034 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
4035 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4036 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4040 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4041 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4045 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
4046 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
4047 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
4049 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4050 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4054 SetLastError(STATUS_ACCESS_VIOLATION
);
4061 struct PATH_LEN_CONSTRAINT
4063 BOOL fPathLenConstraint
;
4064 DWORD dwPathLenConstraint
;
4067 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
4068 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4069 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4073 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4074 pvStructInfo
, *pcbStructInfo
);
4078 if (pbEncoded
[0] == ASN_INTEGER
)
4080 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
4083 *pcbStructInfo
= bytesNeeded
;
4084 else if (*pcbStructInfo
< bytesNeeded
)
4086 SetLastError(ERROR_MORE_DATA
);
4087 *pcbStructInfo
= bytesNeeded
;
4092 struct PATH_LEN_CONSTRAINT
*constraint
=
4093 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
4094 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
4096 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
4097 pbEncoded
, cbEncoded
, 0, NULL
,
4098 &constraint
->dwPathLenConstraint
, &size
);
4100 constraint
->fPathLenConstraint
= TRUE
;
4101 TRACE("got an int, dwPathLenConstraint is %ld\n",
4102 constraint
->dwPathLenConstraint
);
4107 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4111 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4115 static BOOL WINAPI
CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType
,
4116 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4117 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4120 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
4121 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
4122 offsetof(CERT_NAME_BLOB
, pbData
) };
4123 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
4125 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4126 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4128 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4129 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4130 entries
? entries
->rgItems
: NULL
);
4131 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
4135 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
4136 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4137 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4143 struct AsnDecodeSequenceItem items
[] = {
4144 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
4145 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
4146 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
4147 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
4148 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
4149 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
4150 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
4151 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
4152 sizeof(struct GenericArray
), TRUE
, TRUE
,
4153 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
4156 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4157 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4158 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4162 SetLastError(STATUS_ACCESS_VIOLATION
);
4169 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
4170 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4171 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4177 struct AsnDecodeSequenceItem items
[] = {
4178 { ASN_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
4179 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
4180 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
4181 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
4182 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
4185 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4186 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4187 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4191 SetLastError(STATUS_ACCESS_VIOLATION
);
4198 #define RSA1_MAGIC 0x31415352
4200 struct DECODED_RSA_PUB_KEY
4203 CRYPT_INTEGER_BLOB modulus
;
4206 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4207 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4208 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4214 struct AsnDecodeSequenceItem items
[] = {
4215 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4216 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4217 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4219 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4220 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4222 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4225 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4226 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4227 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4230 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4231 decodedKey
->modulus
.cbData
;
4235 *pcbStructInfo
= bytesNeeded
;
4238 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4239 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4242 RSAPUBKEY
*rsaPubKey
;
4244 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4245 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4246 hdr
= (BLOBHEADER
*)pvStructInfo
;
4247 hdr
->bType
= PUBLICKEYBLOB
;
4248 hdr
->bVersion
= CUR_BLOB_VERSION
;
4250 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4251 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4252 sizeof(BLOBHEADER
));
4253 rsaPubKey
->magic
= RSA1_MAGIC
;
4254 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4255 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4256 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4257 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4258 decodedKey
->modulus
.cbData
);
4260 LocalFree(decodedKey
);
4265 SetLastError(STATUS_ACCESS_VIOLATION
);
4272 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
4273 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4274 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4277 DWORD bytesNeeded
, dataLen
;
4279 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4280 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4282 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4284 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4285 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4287 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4289 *pcbStructInfo
= bytesNeeded
;
4290 else if (*pcbStructInfo
< bytesNeeded
)
4292 SetLastError(ERROR_MORE_DATA
);
4293 *pcbStructInfo
= bytesNeeded
;
4298 CRYPT_DATA_BLOB
*blob
;
4299 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4301 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4302 blob
->cbData
= dataLen
;
4303 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4304 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4307 assert(blob
->pbData
);
4309 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4317 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4318 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4319 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4323 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4324 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4332 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4335 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
4337 SetLastError(CRYPT_E_ASN1_BADTAG
);
4340 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4341 lpszStructType
, pbEncoded
, cbEncoded
,
4342 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4345 *pcbStructInfo
= bytesNeeded
;
4346 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4347 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4349 CRYPT_DATA_BLOB
*blob
;
4351 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4352 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4353 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4354 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
4355 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4356 lpszStructType
, pbEncoded
, cbEncoded
,
4357 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4364 SetLastError(STATUS_ACCESS_VIOLATION
);
4371 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4372 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4373 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4377 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4378 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4380 if (pbEncoded
[0] == ASN_BITSTRING
)
4382 DWORD bytesNeeded
, dataLen
;
4384 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4386 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4387 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4389 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4391 *pcbStructInfo
= bytesNeeded
;
4392 else if (*pcbStructInfo
< bytesNeeded
)
4394 *pcbStructInfo
= bytesNeeded
;
4395 SetLastError(ERROR_MORE_DATA
);
4400 CRYPT_BIT_BLOB
*blob
;
4402 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4403 blob
->cbData
= dataLen
- 1;
4404 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4405 GET_LEN_BYTES(pbEncoded
[1]));
4406 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4408 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4409 GET_LEN_BYTES(pbEncoded
[1]);
4413 assert(blob
->pbData
);
4416 BYTE mask
= 0xff << blob
->cUnusedBits
;
4418 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4419 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4420 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4428 SetLastError(CRYPT_E_ASN1_BADTAG
);
4431 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4435 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4436 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4437 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4441 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4442 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4448 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4449 lpszStructType
, pbEncoded
, cbEncoded
,
4450 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4453 *pcbStructInfo
= bytesNeeded
;
4454 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4455 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4457 CRYPT_BIT_BLOB
*blob
;
4459 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4460 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4461 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4462 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4463 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4464 lpszStructType
, pbEncoded
, cbEncoded
,
4465 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4472 SetLastError(STATUS_ACCESS_VIOLATION
);
4476 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4480 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4481 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4482 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4488 *pcbStructInfo
= sizeof(int);
4493 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4494 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4495 DWORD size
= sizeof(buf
);
4497 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4498 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4499 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4502 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4503 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4507 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4508 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4509 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4511 /* initialize to a negative value to sign-extend */
4516 for (i
= 0; i
< blob
->cbData
; i
++)
4519 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4521 memcpy(pvStructInfo
, &val
, sizeof(int));
4524 else if (GetLastError() == ERROR_MORE_DATA
)
4525 SetLastError(CRYPT_E_ASN1_LARGE
);
4529 SetLastError(STATUS_ACCESS_VIOLATION
);
4536 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4537 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4538 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4542 if (pbEncoded
[0] == ASN_INTEGER
)
4544 DWORD bytesNeeded
, dataLen
;
4546 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4548 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4550 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4552 *pcbStructInfo
= bytesNeeded
;
4553 else if (*pcbStructInfo
< bytesNeeded
)
4555 *pcbStructInfo
= bytesNeeded
;
4556 SetLastError(ERROR_MORE_DATA
);
4561 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4563 blob
->cbData
= dataLen
;
4564 assert(blob
->pbData
);
4569 for (i
= 0; i
< blob
->cbData
; i
++)
4571 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4580 SetLastError(CRYPT_E_ASN1_BADTAG
);
4586 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4587 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4588 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4596 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4597 lpszStructType
, pbEncoded
, cbEncoded
,
4598 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4601 *pcbStructInfo
= bytesNeeded
;
4602 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4603 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4605 CRYPT_INTEGER_BLOB
*blob
;
4607 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4608 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4609 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4610 blob
->pbData
= (BYTE
*)pvStructInfo
+
4611 sizeof(CRYPT_INTEGER_BLOB
);
4612 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4613 lpszStructType
, pbEncoded
, cbEncoded
,
4614 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4621 SetLastError(STATUS_ACCESS_VIOLATION
);
4628 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
4629 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
4630 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4631 void *pvStructInfo
, DWORD
*pcbStructInfo
)
4635 if (pbEncoded
[0] == ASN_INTEGER
)
4637 DWORD bytesNeeded
, dataLen
;
4639 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4641 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4643 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4645 *pcbStructInfo
= bytesNeeded
;
4646 else if (*pcbStructInfo
< bytesNeeded
)
4648 *pcbStructInfo
= bytesNeeded
;
4649 SetLastError(ERROR_MORE_DATA
);
4654 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4656 blob
->cbData
= dataLen
;
4657 assert(blob
->pbData
);
4658 /* remove leading zero byte if it exists */
4659 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4668 for (i
= 0; i
< blob
->cbData
; i
++)
4670 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4679 SetLastError(CRYPT_E_ASN1_BADTAG
);
4685 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4686 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4687 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4695 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4696 lpszStructType
, pbEncoded
, cbEncoded
,
4697 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4700 *pcbStructInfo
= bytesNeeded
;
4701 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4702 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4704 CRYPT_INTEGER_BLOB
*blob
;
4706 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4707 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4708 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4709 blob
->pbData
= (BYTE
*)pvStructInfo
+
4710 sizeof(CRYPT_INTEGER_BLOB
);
4711 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4712 lpszStructType
, pbEncoded
, cbEncoded
,
4713 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4720 SetLastError(STATUS_ACCESS_VIOLATION
);
4727 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4728 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4729 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4735 *pcbStructInfo
= sizeof(int);
4740 if (pbEncoded
[0] == ASN_ENUMERATED
)
4742 unsigned int val
= 0, i
;
4746 SetLastError(CRYPT_E_ASN1_EOD
);
4749 else if (pbEncoded
[1] == 0)
4751 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4756 /* A little strange looking, but we have to accept a sign byte:
4757 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4758 * assuming a small length is okay here, it has to be in short
4761 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4763 SetLastError(CRYPT_E_ASN1_LARGE
);
4766 for (i
= 0; i
< pbEncoded
[1]; i
++)
4769 val
|= pbEncoded
[2 + i
];
4771 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4772 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4774 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4775 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4776 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4782 SetLastError(CRYPT_E_ASN1_BADTAG
);
4788 SetLastError(STATUS_ACCESS_VIOLATION
);
4795 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4798 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4803 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4805 if (!isdigit(*(pbEncoded))) \
4807 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4813 (word) += *(pbEncoded)++ - '0'; \
4818 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
4819 SYSTEMTIME
*sysTime
)
4826 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
4828 WORD hours
, minutes
= 0;
4829 BYTE sign
= *pbEncoded
++;
4832 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
4833 if (ret
&& hours
>= 24)
4835 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4840 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
4841 if (ret
&& minutes
>= 60)
4843 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4851 sysTime
->wHour
+= hours
;
4852 sysTime
->wMinute
+= minutes
;
4856 if (hours
> sysTime
->wHour
)
4859 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
4862 sysTime
->wHour
-= hours
;
4863 if (minutes
> sysTime
->wMinute
)
4866 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
4869 sysTime
->wMinute
-= minutes
;
4876 SetLastError(STATUS_ACCESS_VIOLATION
);
4883 #define MIN_ENCODED_TIME_LENGTH 10
4885 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
4886 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4887 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4893 *pcbStructInfo
= sizeof(FILETIME
);
4899 if (pbEncoded
[0] == ASN_UTCTIME
)
4903 SetLastError(CRYPT_E_ASN1_EOD
);
4906 else if (pbEncoded
[1] > 0x7f)
4908 /* long-form date strings really can't be valid */
4909 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4914 SYSTEMTIME sysTime
= { 0 };
4915 BYTE len
= pbEncoded
[1];
4917 if (len
< MIN_ENCODED_TIME_LENGTH
)
4919 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4925 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
4926 if (sysTime
.wYear
>= 50)
4927 sysTime
.wYear
+= 1900;
4929 sysTime
.wYear
+= 2000;
4930 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
4931 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
4932 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
4933 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
4936 if (len
>= 2 && isdigit(*pbEncoded
) &&
4937 isdigit(*(pbEncoded
+ 1)))
4938 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4940 else if (isdigit(*pbEncoded
))
4941 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
4944 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
4947 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4948 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4951 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4952 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4953 ret
= SystemTimeToFileTime(&sysTime
,
4954 (FILETIME
*)pvStructInfo
);
4961 SetLastError(CRYPT_E_ASN1_BADTAG
);
4967 SetLastError(STATUS_ACCESS_VIOLATION
);
4974 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
4975 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4976 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4982 *pcbStructInfo
= sizeof(FILETIME
);
4988 if (pbEncoded
[0] == ASN_GENERALTIME
)
4992 SetLastError(CRYPT_E_ASN1_EOD
);
4995 else if (pbEncoded
[1] > 0x7f)
4997 /* long-form date strings really can't be valid */
4998 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5003 BYTE len
= pbEncoded
[1];
5005 if (len
< MIN_ENCODED_TIME_LENGTH
)
5007 SetLastError(CRYPT_E_ASN1_CORRUPT
);
5012 SYSTEMTIME sysTime
= { 0 };
5015 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
5016 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
5017 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
5018 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
5021 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5024 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
5026 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
5033 /* workaround macro weirdness */
5034 digits
= min(len
, 3);
5035 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
5036 sysTime
.wMilliseconds
);
5039 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5042 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5043 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5046 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5047 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5048 ret
= SystemTimeToFileTime(&sysTime
,
5049 (FILETIME
*)pvStructInfo
);
5056 SetLastError(CRYPT_E_ASN1_BADTAG
);
5062 SetLastError(STATUS_ACCESS_VIOLATION
);
5069 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5070 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5071 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5077 if (pbEncoded
[0] == ASN_UTCTIME
)
5078 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5079 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5081 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5082 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5083 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5084 pvStructInfo
, pcbStructInfo
);
5087 SetLastError(CRYPT_E_ASN1_BADTAG
);
5093 SetLastError(STATUS_ACCESS_VIOLATION
);
5100 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5101 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5102 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5108 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5110 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5112 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5117 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5118 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5120 ptr
= pbEncoded
+ 1 + lenBytes
;
5121 remainingLen
= dataLen
;
5122 while (ret
&& remainingLen
)
5126 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5129 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5131 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5132 ptr
+= 1 + nextLenBytes
+ nextLen
;
5133 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5134 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5135 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5141 CRYPT_SEQUENCE_OF_ANY
*seq
;
5145 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5146 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5148 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5149 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5150 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5151 seq
->cValue
= cValue
;
5152 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5154 nextPtr
= (BYTE
*)seq
->rgValue
+
5155 cValue
* sizeof(CRYPT_DER_BLOB
);
5156 ptr
= pbEncoded
+ 1 + lenBytes
;
5157 remainingLen
= dataLen
;
5159 while (ret
&& remainingLen
)
5163 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5166 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5168 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5170 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5171 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5174 seq
->rgValue
[i
].pbData
= nextPtr
;
5175 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5177 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5179 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5180 ptr
+= 1 + nextLenBytes
+ nextLen
;
5190 SetLastError(CRYPT_E_ASN1_BADTAG
);
5196 SetLastError(STATUS_ACCESS_VIOLATION
);
5203 static BOOL WINAPI
CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType
,
5204 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5205 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5207 struct AsnDecodeSequenceItem items
[] = {
5208 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
5209 DistPointName
), CRYPT_AsnDecodeAltNameInternal
,
5210 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
5211 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
5212 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
5213 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
5214 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
5215 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
5216 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
5217 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
5221 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
5222 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
5223 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
5227 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
5228 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5229 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5233 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
5234 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
5238 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
5239 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
5240 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
5242 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
5243 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
5247 SetLastError(STATUS_ACCESS_VIOLATION
);
5254 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
5255 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5256 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5260 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
5261 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
5265 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
5266 CRYPT_AsnDecodeOidWrapper
, sizeof(LPSTR
), TRUE
, 0 };
5268 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
5269 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
5273 SetLastError(STATUS_ACCESS_VIOLATION
);
5280 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5281 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5282 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5284 static HCRYPTOIDFUNCSET set
= NULL
;
5286 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5287 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5289 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5290 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5291 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5293 if (!pvStructInfo
&& !pcbStructInfo
)
5295 SetLastError(ERROR_INVALID_PARAMETER
);
5298 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5299 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5301 SetLastError(ERROR_FILE_NOT_FOUND
);
5306 SetLastError(CRYPT_E_ASN1_EOD
);
5309 if (cbEncoded
> MAX_ENCODED_LEN
)
5311 SetLastError(CRYPT_E_ASN1_LARGE
);
5315 SetLastError(NOERROR
);
5316 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5317 *(BYTE
**)pvStructInfo
= NULL
;
5318 if (!HIWORD(lpszStructType
))
5320 switch (LOWORD(lpszStructType
))
5322 case (WORD
)X509_CERT
:
5323 decodeFunc
= CRYPT_AsnDecodeCert
;
5325 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5326 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5328 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5329 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5331 case (WORD
)X509_EXTENSIONS
:
5332 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5334 case (WORD
)X509_NAME
:
5335 decodeFunc
= CRYPT_AsnDecodeName
;
5337 case (WORD
)X509_PUBLIC_KEY_INFO
:
5338 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5340 case (WORD
)X509_ALTERNATE_NAME
:
5341 decodeFunc
= CRYPT_AsnDecodeAltName
;
5343 case (WORD
)X509_BASIC_CONSTRAINTS
:
5344 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
5346 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5347 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5349 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5350 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5352 case (WORD
)X509_OCTET_STRING
:
5353 decodeFunc
= CRYPT_AsnDecodeOctets
;
5355 case (WORD
)X509_BITS
:
5356 case (WORD
)X509_KEY_USAGE
:
5357 decodeFunc
= CRYPT_AsnDecodeBits
;
5359 case (WORD
)X509_INTEGER
:
5360 decodeFunc
= CRYPT_AsnDecodeInt
;
5362 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5363 decodeFunc
= CRYPT_AsnDecodeInteger
;
5365 case (WORD
)X509_MULTI_BYTE_UINT
:
5366 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5368 case (WORD
)X509_ENUMERATED
:
5369 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5371 case (WORD
)X509_CHOICE_OF_TIME
:
5372 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5374 case (WORD
)X509_SEQUENCE_OF_ANY
:
5375 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5377 case (WORD
)PKCS_UTC_TIME
:
5378 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5380 case (WORD
)X509_CRL_DIST_POINTS
:
5381 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
5383 case (WORD
)X509_ENHANCED_KEY_USAGE
:
5384 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
5387 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5390 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5391 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5392 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5393 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5394 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5395 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5396 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5397 decodeFunc
= CRYPT_AsnDecodeBits
;
5398 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5399 decodeFunc
= CRYPT_AsnDecodeOctets
;
5400 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
5401 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
5402 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5403 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5404 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5405 decodeFunc
= CRYPT_AsnDecodeAltName
;
5406 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5407 decodeFunc
= CRYPT_AsnDecodeAltName
;
5408 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5409 decodeFunc
= CRYPT_AsnDecodeAltName
;
5410 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5411 decodeFunc
= CRYPT_AsnDecodeAltName
;
5412 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5413 decodeFunc
= CRYPT_AsnDecodeAltName
;
5414 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
5415 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
5416 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
5417 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
5419 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5420 debugstr_a(lpszStructType
));
5424 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
5425 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
5426 (void **)&decodeFunc
, &hFunc
);
5429 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5430 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5432 SetLastError(ERROR_FILE_NOT_FOUND
);
5434 CryptFreeOIDFunctionAddress(hFunc
, 0);
5438 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5439 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5441 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5442 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5445 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5446 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5447 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5452 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5453 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5456 if (!pszPublicKeyObjId
)
5457 pszPublicKeyObjId
= szOID_RSA_RSA
;
5458 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5462 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5465 LPBYTE pubKey
= CryptMemAlloc(keySize
);
5469 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
5473 DWORD encodedLen
= 0;
5475 ret
= CryptEncodeObject(dwCertEncodingType
,
5476 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5479 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5480 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5483 *pcbInfo
= sizeNeeded
;
5484 else if (*pcbInfo
< sizeNeeded
)
5486 SetLastError(ERROR_MORE_DATA
);
5487 *pcbInfo
= sizeNeeded
;
5492 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5493 sizeof(CERT_PUBLIC_KEY_INFO
);
5494 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5496 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5497 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5498 pInfo
->PublicKey
.pbData
=
5499 (BYTE
*)pInfo
->Algorithm
.pszObjId
5500 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5501 pInfo
->PublicKey
.cbData
= encodedLen
;
5502 pInfo
->PublicKey
.cUnusedBits
= 0;
5503 ret
= CryptEncodeObject(dwCertEncodingType
,
5504 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5505 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5509 CryptMemFree(pubKey
);
5514 CryptDestroyKey(key
);
5519 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5520 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5521 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5523 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5524 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5525 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5527 static HCRYPTOIDFUNCSET set
= NULL
;
5529 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5530 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5532 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5533 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5538 SetLastError(ERROR_INVALID_PARAMETER
);
5542 if (pszPublicKeyObjId
)
5545 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
5547 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
5548 0, (void **)&exportFunc
, &hFunc
);
5551 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
5552 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5553 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5555 CryptFreeOIDFunctionAddress(hFunc
, 0);
5559 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5560 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5562 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5566 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5567 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5568 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5571 DWORD pubKeySize
= 0;
5573 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5574 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5576 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5577 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5580 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
5584 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5585 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5588 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5590 CryptMemFree(pubKey
);
5598 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5599 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5600 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5602 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5603 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5604 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5606 static HCRYPTOIDFUNCSET set
= NULL
;
5608 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5609 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5611 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5612 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5615 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
5616 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
5617 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
5619 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
5620 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
5623 CryptFreeOIDFunctionAddress(hFunc
, 0);