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 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
145 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
146 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
147 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
148 /* Internal function */
149 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
150 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
151 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
152 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
153 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
154 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
155 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
156 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
157 * member has been initialized, doesn't do exception handling, and doesn't do
160 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
161 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
162 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
163 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
164 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
165 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
166 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
167 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
168 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
169 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
170 * member has been initialized, doesn't do exception handling, and doesn't do
173 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
174 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
175 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
176 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
177 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
178 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
179 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
180 void *pvStructInfo
, DWORD
*pcbStructInfo
);
182 BOOL WINAPI
CryptEncodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
183 const void *pvStructInfo
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
185 static HCRYPTOIDFUNCSET set
= NULL
;
187 HCRYPTOIDFUNCADDR hFunc
;
188 CryptEncodeObjectFunc pCryptEncodeObject
;
190 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
191 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
194 if (!pbEncoded
&& !pcbEncoded
)
196 SetLastError(ERROR_INVALID_PARAMETER
);
200 /* Try registered DLL first.. */
202 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC
, 0);
203 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
204 (void **)&pCryptEncodeObject
, &hFunc
);
205 if (pCryptEncodeObject
)
207 ret
= pCryptEncodeObject(dwCertEncodingType
, lpszStructType
,
208 pvStructInfo
, pbEncoded
, pcbEncoded
);
209 CryptFreeOIDFunctionAddress(hFunc
, 0);
213 /* If not, use CryptEncodeObjectEx */
214 ret
= CryptEncodeObjectEx(dwCertEncodingType
, lpszStructType
,
215 pvStructInfo
, 0, NULL
, pbEncoded
, pcbEncoded
);
220 /* Helper function to check *pcbEncoded, set it to the required size, and
221 * optionally to allocate memory. Assumes pbEncoded is not NULL.
222 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
223 * pointer to the newly allocated memory.
225 static BOOL
CRYPT_EncodeEnsureSpace(DWORD dwFlags
,
226 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
,
231 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
233 if (pEncodePara
&& pEncodePara
->pfnAlloc
)
234 *(BYTE
**)pbEncoded
= pEncodePara
->pfnAlloc(bytesNeeded
);
236 *(BYTE
**)pbEncoded
= LocalAlloc(0, bytesNeeded
);
237 if (!*(BYTE
**)pbEncoded
)
240 *pcbEncoded
= bytesNeeded
;
242 else if (bytesNeeded
> *pcbEncoded
)
244 *pcbEncoded
= bytesNeeded
;
245 SetLastError(ERROR_MORE_DATA
);
251 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
253 DWORD bytesNeeded
, significantBytes
= 0;
261 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
262 temp
<<= 8, significantBytes
--)
264 bytesNeeded
= significantBytes
+ 1;
268 *pcbEncoded
= bytesNeeded
;
271 if (*pcbEncoded
< bytesNeeded
)
273 SetLastError(ERROR_MORE_DATA
);
277 *pbEncoded
= (BYTE
)len
;
282 *pbEncoded
++ = significantBytes
| 0x80;
283 for (i
= 0; i
< significantBytes
; i
++)
285 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
289 *pcbEncoded
= bytesNeeded
;
293 struct AsnEncodeSequenceItem
295 const void *pvStructInfo
;
296 CryptEncodeObjectExFunc encodeFunc
;
297 DWORD size
; /* used during encoding, not for your use */
300 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
301 struct AsnEncodeSequenceItem items
[], DWORD cItem
, DWORD dwFlags
,
302 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
305 DWORD i
, dataLen
= 0;
307 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", items
, cItem
, dwFlags
, pEncodePara
,
308 pbEncoded
, *pcbEncoded
);
309 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
311 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
312 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
313 NULL
, &items
[i
].size
);
314 /* Some functions propagate their errors through the size */
316 *pcbEncoded
= items
[i
].size
;
317 dataLen
+= items
[i
].size
;
321 DWORD lenBytes
, bytesNeeded
;
323 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
324 bytesNeeded
= 1 + lenBytes
+ dataLen
;
326 *pcbEncoded
= bytesNeeded
;
329 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
330 pcbEncoded
, bytesNeeded
)))
332 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
333 pbEncoded
= *(BYTE
**)pbEncoded
;
334 *pbEncoded
++ = ASN_SEQUENCE
;
335 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
336 pbEncoded
+= lenBytes
;
337 for (i
= 0; ret
&& i
< cItem
; i
++)
339 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
340 items
[i
].pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
,
341 NULL
, pbEncoded
, &items
[i
].size
);
342 /* Some functions propagate their errors through the size */
344 *pcbEncoded
= items
[i
].size
;
345 pbEncoded
+= items
[i
].size
;
350 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
354 struct AsnConstructedItem
357 const void *pvStructInfo
;
358 CryptEncodeObjectExFunc encodeFunc
;
361 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
362 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
363 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
366 const struct AsnConstructedItem
*item
=
367 (const struct AsnConstructedItem
*)pvStructInfo
;
370 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
371 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &len
)))
373 DWORD dataLen
, bytesNeeded
;
375 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
376 bytesNeeded
= 1 + dataLen
+ len
;
378 *pcbEncoded
= bytesNeeded
;
379 else if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
380 pbEncoded
, pcbEncoded
, bytesNeeded
)))
382 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
383 pbEncoded
= *(BYTE
**)pbEncoded
;
384 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
385 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
386 pbEncoded
+= dataLen
;
387 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
388 item
->pvStructInfo
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
,
392 /* Some functions propagate their errors through the size */
399 /* Some functions propagate their errors through the size */
405 struct AsnEncodeTagSwappedItem
408 const void *pvStructInfo
;
409 CryptEncodeObjectExFunc encodeFunc
;
412 /* Sort of a wacky hack, it encodes something using the struct
413 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
414 * given in the struct AsnEncodeTagSwappedItem.
416 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
417 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
418 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
421 const struct AsnEncodeTagSwappedItem
*item
=
422 (const struct AsnEncodeTagSwappedItem
*)pvStructInfo
;
424 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
425 item
->pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
426 if (ret
&& pbEncoded
)
427 *pbEncoded
= item
->tag
;
431 static BOOL WINAPI
CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType
,
432 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
433 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
435 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
438 /* CERT_V1 is not encoded */
446 struct AsnConstructedItem item
= { 0, ver
, CRYPT_AsnEncodeInt
};
448 ret
= CRYPT_AsnEncodeConstructed(dwCertEncodingType
, X509_INTEGER
,
449 &item
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
454 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
455 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
456 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
458 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
463 *pcbEncoded
= blob
->cbData
;
466 else if (*pcbEncoded
< blob
->cbData
)
468 *pcbEncoded
= blob
->cbData
;
469 SetLastError(ERROR_MORE_DATA
);
475 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
476 *pcbEncoded
= blob
->cbData
;
482 static BOOL WINAPI
CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType
,
483 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
484 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
487 /* This has two filetimes in a row, a NotBefore and a NotAfter */
488 const FILETIME
*timePtr
= (const FILETIME
*)pvStructInfo
;
489 struct AsnEncodeSequenceItem items
[] = {
490 { timePtr
++, CRYPT_AsnEncodeChoiceOfTime
, 0 },
491 { timePtr
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
494 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
495 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
500 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmId(
501 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
502 DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
,
505 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
506 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
508 struct AsnEncodeSequenceItem items
[] = {
509 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
510 { &algo
->Parameters
, CRYPT_CopyEncodedBlob
, 0 },
513 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
514 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
519 static BOOL WINAPI
CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType
,
520 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
521 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
527 const CERT_PUBLIC_KEY_INFO
*info
=
528 (const CERT_PUBLIC_KEY_INFO
*)pvStructInfo
;
529 struct AsnEncodeSequenceItem items
[] = {
530 { &info
->Algorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
531 { &info
->PublicKey
, CRYPT_AsnEncodeBits
, 0 },
534 TRACE("Encoding public key with OID %s\n",
535 debugstr_a(info
->Algorithm
.pszObjId
));
536 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
537 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
542 SetLastError(STATUS_ACCESS_VIOLATION
);
549 static BOOL WINAPI
CRYPT_AsnEncodeCert(DWORD dwCertEncodingType
,
550 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
551 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
557 const CERT_SIGNED_CONTENT_INFO
*info
=
558 (const CERT_SIGNED_CONTENT_INFO
*)pvStructInfo
;
559 struct AsnEncodeSequenceItem items
[] = {
560 { &info
->ToBeSigned
, CRYPT_CopyEncodedBlob
, 0 },
561 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
562 { &info
->Signature
, CRYPT_AsnEncodeBitsSwapBytes
, 0 },
565 if (dwFlags
& CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
566 items
[2].encodeFunc
= CRYPT_AsnEncodeBits
;
567 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
568 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
573 SetLastError(STATUS_ACCESS_VIOLATION
);
580 /* Like in Windows, this blithely ignores the validity of the passed-in
581 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
582 * decode properly, see CRYPT_AsnDecodeCertInfo.
584 static BOOL WINAPI
CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType
,
585 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
586 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
592 const CERT_INFO
*info
= (const CERT_INFO
*)pvStructInfo
;
593 struct AsnEncodeSequenceItem items
[10] = {
594 { &info
->dwVersion
, CRYPT_AsnEncodeCertVersion
, 0 },
595 { &info
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
596 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
597 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
598 { &info
->NotBefore
, CRYPT_AsnEncodeValidity
, 0 },
599 { &info
->Subject
, CRYPT_CopyEncodedBlob
, 0 },
600 { &info
->SubjectPublicKeyInfo
, CRYPT_AsnEncodePubKeyInfo
, 0 },
603 struct AsnConstructedItem constructed
[3] = { { 0 } };
604 DWORD cItem
= 7, cConstructed
= 0;
606 if (info
->IssuerUniqueId
.cbData
)
608 constructed
[cConstructed
].tag
= 1;
609 constructed
[cConstructed
].pvStructInfo
= &info
->IssuerUniqueId
;
610 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
611 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
612 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
616 if (info
->SubjectUniqueId
.cbData
)
618 constructed
[cConstructed
].tag
= 2;
619 constructed
[cConstructed
].pvStructInfo
= &info
->SubjectUniqueId
;
620 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeBits
;
621 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
622 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
626 if (info
->cExtension
)
628 constructed
[cConstructed
].tag
= 3;
629 constructed
[cConstructed
].pvStructInfo
= &info
->cExtension
;
630 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
631 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
632 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
637 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
638 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
642 SetLastError(STATUS_ACCESS_VIOLATION
);
649 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY
*entry
,
650 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
652 struct AsnEncodeSequenceItem items
[3] = {
653 { &entry
->SerialNumber
, CRYPT_AsnEncodeInteger
, 0 },
654 { &entry
->RevocationDate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
660 TRACE("%p, %p, %p\n", entry
, pbEncoded
, pcbEncoded
);
662 if (entry
->cExtension
)
664 items
[cItem
].pvStructInfo
= &entry
->cExtension
;
665 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
669 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
670 pbEncoded
, pcbEncoded
);
672 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
676 static BOOL WINAPI
CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType
,
677 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
678 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
680 DWORD cCRLEntry
= *(const DWORD
*)pvStructInfo
;
681 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
682 const CRL_ENTRY
*rgCRLEntry
= *(const CRL_ENTRY
**)
683 ((const BYTE
*)pvStructInfo
+ sizeof(DWORD
));
686 for (i
= 0, dataLen
= 0; ret
&& i
< cCRLEntry
; i
++)
690 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], NULL
, &size
);
694 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
695 bytesNeeded
= 1 + lenBytes
+ dataLen
;
697 *pcbEncoded
= bytesNeeded
;
700 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
701 pcbEncoded
, bytesNeeded
)))
703 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
704 pbEncoded
= *(BYTE
**)pbEncoded
;
705 *pbEncoded
++ = ASN_SEQUENCEOF
;
706 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
707 pbEncoded
+= lenBytes
;
708 for (i
= 0; i
< cCRLEntry
; i
++)
710 DWORD size
= dataLen
;
712 ret
= CRYPT_AsnEncodeCRLEntry(&rgCRLEntry
[i
], pbEncoded
, &size
);
721 static BOOL WINAPI
CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType
,
722 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
723 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
725 const DWORD
*ver
= (const DWORD
*)pvStructInfo
;
728 /* CRL_V1 is not encoded */
735 ret
= CRYPT_AsnEncodeInt(dwCertEncodingType
, X509_INTEGER
, ver
,
736 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
740 /* Like in Windows, this blithely ignores the validity of the passed-in
741 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
742 * decode properly, see CRYPT_AsnDecodeCRLInfo.
744 static BOOL WINAPI
CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType
,
745 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
746 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
752 const CRL_INFO
*info
= (const CRL_INFO
*)pvStructInfo
;
753 struct AsnEncodeSequenceItem items
[7] = {
754 { &info
->dwVersion
, CRYPT_AsnEncodeCRLVersion
, 0 },
755 { &info
->SignatureAlgorithm
, CRYPT_AsnEncodeAlgorithmId
, 0 },
756 { &info
->Issuer
, CRYPT_CopyEncodedBlob
, 0 },
757 { &info
->ThisUpdate
, CRYPT_AsnEncodeChoiceOfTime
, 0 },
762 if (info
->NextUpdate
.dwLowDateTime
|| info
->NextUpdate
.dwHighDateTime
)
764 items
[cItem
].pvStructInfo
= &info
->NextUpdate
;
765 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
770 items
[cItem
].pvStructInfo
= &info
->cCRLEntry
;
771 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeCRLEntries
;
774 if (info
->cExtension
)
776 items
[cItem
].pvStructInfo
= &info
->cExtension
;
777 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeExtensions
;
781 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
782 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
786 SetLastError(STATUS_ACCESS_VIOLATION
);
793 static BOOL
CRYPT_AsnEncodeExtension(CERT_EXTENSION
*ext
, BYTE
*pbEncoded
,
797 struct AsnEncodeSequenceItem items
[3] = {
798 { ext
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
804 TRACE("%p, %p, %ld\n", ext
, pbEncoded
, *pcbEncoded
);
808 items
[cItem
].pvStructInfo
= &ext
->fCritical
;
809 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
812 items
[cItem
].pvStructInfo
= &ext
->Value
;
813 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeOctets
;
816 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
817 pbEncoded
, pcbEncoded
);
818 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
822 static BOOL WINAPI
CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType
,
823 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
824 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
830 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
831 const CERT_EXTENSIONS
*exts
= (const CERT_EXTENSIONS
*)pvStructInfo
;
834 for (i
= 0, dataLen
= 0; ret
&& i
< exts
->cExtension
; i
++)
838 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
], NULL
, &size
);
842 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
843 bytesNeeded
= 1 + lenBytes
+ dataLen
;
845 *pcbEncoded
= bytesNeeded
;
848 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
849 pcbEncoded
, bytesNeeded
)))
851 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
852 pbEncoded
= *(BYTE
**)pbEncoded
;
853 *pbEncoded
++ = ASN_SEQUENCEOF
;
854 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
855 pbEncoded
+= lenBytes
;
856 for (i
= 0; i
< exts
->cExtension
; i
++)
858 DWORD size
= dataLen
;
860 ret
= CRYPT_AsnEncodeExtension(&exts
->rgExtension
[i
],
870 SetLastError(STATUS_ACCESS_VIOLATION
);
877 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
878 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
879 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
881 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
882 DWORD bytesNeeded
= 0, lenBytes
;
887 TRACE("%s\n", debugstr_a(pszObjId
));
894 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
896 SetLastError(CRYPT_E_ASN1_ERROR
);
900 firstByte
= val1
* 40 + val2
;
901 ptr
= pszObjId
+ firstPos
;
906 /* note I assume each component is at most 32-bits long in base 2 */
907 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
909 if (val1
>= 0x10000000)
911 else if (val1
>= 0x200000)
913 else if (val1
>= 0x4000)
915 else if (val1
>= 0x80)
925 SetLastError(CRYPT_E_ASN1_ERROR
);
929 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
933 bytesNeeded
+= 1 + lenBytes
;
936 if (*pcbEncoded
< bytesNeeded
)
938 SetLastError(ERROR_MORE_DATA
);
943 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
944 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
945 pbEncoded
+= lenBytes
;
951 *pbEncoded
++ = firstByte
;
952 ptr
= pszObjId
+ firstPos
;
955 sscanf(ptr
, "%d%n", &val
, &pos
);
957 unsigned char outBytes
[5];
960 if (val
>= 0x10000000)
962 else if (val
>= 0x200000)
964 else if (val
>= 0x4000)
966 else if (val
>= 0x80)
970 for (i
= numBytes
; i
> 0; i
--)
972 outBytes
[i
- 1] = val
& 0x7f;
975 for (i
= 0; i
< numBytes
- 1; i
++)
976 *pbEncoded
++ = outBytes
[i
] | 0x80;
977 *pbEncoded
++ = outBytes
[i
];
986 *pcbEncoded
= bytesNeeded
;
990 static BOOL WINAPI
CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType
,
991 CERT_NAME_VALUE
*value
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
994 DWORD bytesNeeded
, lenBytes
, encodedLen
;
997 switch (value
->dwValueType
)
999 case CERT_RDN_NUMERIC_STRING
:
1000 tag
= ASN_NUMERICSTRING
;
1001 encodedLen
= value
->Value
.cbData
;
1003 case CERT_RDN_PRINTABLE_STRING
:
1004 tag
= ASN_PRINTABLESTRING
;
1005 encodedLen
= value
->Value
.cbData
;
1007 case CERT_RDN_IA5_STRING
:
1008 tag
= ASN_IA5STRING
;
1009 encodedLen
= value
->Value
.cbData
;
1011 case CERT_RDN_ANY_TYPE
:
1012 /* explicitly disallowed */
1013 SetLastError(E_INVALIDARG
);
1016 FIXME("String type %ld unimplemented\n", value
->dwValueType
);
1019 CRYPT_EncodeLen(encodedLen
, NULL
, &lenBytes
);
1020 bytesNeeded
= 1 + lenBytes
+ encodedLen
;
1023 if (*pcbEncoded
< bytesNeeded
)
1025 SetLastError(ERROR_MORE_DATA
);
1031 CRYPT_EncodeLen(encodedLen
, pbEncoded
, &lenBytes
);
1032 pbEncoded
+= lenBytes
;
1033 switch (value
->dwValueType
)
1035 case CERT_RDN_NUMERIC_STRING
:
1036 case CERT_RDN_PRINTABLE_STRING
:
1037 case CERT_RDN_IA5_STRING
:
1038 memcpy(pbEncoded
, value
->Value
.pbData
, value
->Value
.cbData
);
1042 *pcbEncoded
= bytesNeeded
;
1046 static BOOL WINAPI
CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType
,
1047 CERT_RDN_ATTR
*attr
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1049 DWORD bytesNeeded
= 0, lenBytes
, size
;
1052 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
, attr
->pszObjId
,
1053 0, NULL
, NULL
, &size
);
1056 bytesNeeded
+= size
;
1057 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1058 * with dwValueType, so "cast" it to get its encoded size
1060 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1061 (CERT_NAME_VALUE
*)&attr
->dwValueType
, NULL
, &size
);
1064 bytesNeeded
+= size
;
1065 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1066 bytesNeeded
+= 1 + lenBytes
;
1069 if (*pcbEncoded
< bytesNeeded
)
1071 SetLastError(ERROR_MORE_DATA
);
1076 *pbEncoded
++ = ASN_SEQUENCE
;
1077 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1079 pbEncoded
+= lenBytes
;
1080 size
= bytesNeeded
- 1 - lenBytes
;
1081 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
1082 attr
->pszObjId
, 0, NULL
, pbEncoded
, &size
);
1086 size
= bytesNeeded
- 1 - lenBytes
- size
;
1087 ret
= CRYPT_AsnEncodeNameValue(dwCertEncodingType
,
1088 (CERT_NAME_VALUE
*)&attr
->dwValueType
, pbEncoded
,
1093 *pcbEncoded
= bytesNeeded
;
1099 static int BLOBComp(const void *l
, const void *r
)
1101 CRYPT_DER_BLOB
*a
= (CRYPT_DER_BLOB
*)l
, *b
= (CRYPT_DER_BLOB
*)r
;
1104 if (!(ret
= memcmp(a
->pbData
, b
->pbData
, min(a
->cbData
, b
->cbData
))))
1105 ret
= a
->cbData
- b
->cbData
;
1109 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1111 static BOOL WINAPI
CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType
, CERT_RDN
*rdn
,
1112 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1115 CRYPT_DER_BLOB
*blobs
= NULL
;
1119 DWORD bytesNeeded
= 0, lenBytes
, i
;
1125 blobs
= CryptMemAlloc(rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1129 memset(blobs
, 0, rdn
->cRDNAttr
* sizeof(CRYPT_DER_BLOB
));
1131 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1133 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
, &rdn
->rgRDNAttr
[i
],
1134 NULL
, &blobs
[i
].cbData
);
1136 bytesNeeded
+= blobs
[i
].cbData
;
1140 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1141 bytesNeeded
+= 1 + lenBytes
;
1144 if (*pcbEncoded
< bytesNeeded
)
1146 SetLastError(ERROR_MORE_DATA
);
1151 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1153 blobs
[i
].pbData
= CryptMemAlloc(blobs
[i
].cbData
);
1154 if (!blobs
[i
].pbData
)
1157 ret
= CRYPT_AsnEncodeRdnAttr(dwCertEncodingType
,
1158 &rdn
->rgRDNAttr
[i
], blobs
[i
].pbData
,
1163 qsort(blobs
, rdn
->cRDNAttr
, sizeof(CRYPT_DER_BLOB
),
1165 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_SETOF
;
1166 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1168 pbEncoded
+= lenBytes
;
1169 for (i
= 0; ret
&& i
< rdn
->cRDNAttr
; i
++)
1171 memcpy(pbEncoded
, blobs
[i
].pbData
, blobs
[i
].cbData
);
1172 pbEncoded
+= blobs
[i
].cbData
;
1177 *pcbEncoded
= bytesNeeded
;
1181 for (i
= 0; i
< rdn
->cRDNAttr
; i
++)
1182 CryptMemFree(blobs
[i
].pbData
);
1187 SetLastError(STATUS_ACCESS_VIOLATION
);
1191 CryptMemFree(blobs
);
1195 static BOOL WINAPI
CRYPT_AsnEncodeName(DWORD dwCertEncodingType
,
1196 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1197 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1203 const CERT_NAME_INFO
*info
= (const CERT_NAME_INFO
*)pvStructInfo
;
1204 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
1206 TRACE("encoding name with %ld RDNs\n", info
->cRDN
);
1208 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1210 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
, &info
->rgRDN
[i
], NULL
,
1213 bytesNeeded
+= size
;
1215 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
1216 bytesNeeded
+= 1 + lenBytes
;
1220 *pcbEncoded
= bytesNeeded
;
1223 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1224 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1226 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1227 pbEncoded
= *(BYTE
**)pbEncoded
;
1228 *pbEncoded
++ = ASN_SEQUENCEOF
;
1229 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
1231 pbEncoded
+= lenBytes
;
1232 for (i
= 0; ret
&& i
< info
->cRDN
; i
++)
1235 ret
= CRYPT_AsnEncodeRdn(dwCertEncodingType
,
1236 &info
->rgRDN
[i
], pbEncoded
, &size
);
1240 bytesNeeded
-= size
;
1249 SetLastError(STATUS_ACCESS_VIOLATION
);
1256 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1257 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1258 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1260 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1269 else if (*pcbEncoded
< 3)
1272 SetLastError(ERROR_MORE_DATA
);
1278 *pbEncoded
++ = ASN_BOOL
;
1280 *pbEncoded
++ = val
? 0xff : 0;
1283 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1287 static BOOL
CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY
*entry
,
1288 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1294 switch (entry
->dwAltNameChoice
)
1296 case CERT_ALT_NAME_RFC822_NAME
:
1297 case CERT_ALT_NAME_DNS_NAME
:
1298 case CERT_ALT_NAME_URL
:
1299 if (entry
->u
.pwszURL
)
1303 /* Not + 1: don't encode the NULL-terminator */
1304 dataLen
= lstrlenW(entry
->u
.pwszURL
);
1305 for (i
= 0; ret
&& i
< dataLen
; i
++)
1307 if (entry
->u
.pwszURL
[i
] > 0x7f)
1309 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
1318 case CERT_ALT_NAME_IP_ADDRESS
:
1319 dataLen
= entry
->u
.IPAddress
.cbData
;
1321 case CERT_ALT_NAME_REGISTERED_ID
:
1322 /* FIXME: encode OID */
1323 case CERT_ALT_NAME_OTHER_NAME
:
1324 case CERT_ALT_NAME_DIRECTORY_NAME
:
1325 FIXME("name type %ld unimplemented\n", entry
->dwAltNameChoice
);
1328 SetLastError(E_INVALIDARG
);
1333 DWORD bytesNeeded
, lenBytes
;
1335 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1336 bytesNeeded
= 1 + dataLen
+ lenBytes
;
1338 *pcbEncoded
= bytesNeeded
;
1339 else if (*pcbEncoded
< bytesNeeded
)
1341 SetLastError(ERROR_MORE_DATA
);
1342 *pcbEncoded
= bytesNeeded
;
1347 *pbEncoded
++ = ASN_CONTEXT
| (entry
->dwAltNameChoice
- 1);
1348 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1349 pbEncoded
+= lenBytes
;
1350 switch (entry
->dwAltNameChoice
)
1352 case CERT_ALT_NAME_RFC822_NAME
:
1353 case CERT_ALT_NAME_DNS_NAME
:
1354 case CERT_ALT_NAME_URL
:
1358 for (i
= 0; i
< dataLen
; i
++)
1359 *pbEncoded
++ = (BYTE
)entry
->u
.pwszURL
[i
];
1362 case CERT_ALT_NAME_IP_ADDRESS
:
1363 memcpy(pbEncoded
, entry
->u
.IPAddress
.pbData
, dataLen
);
1367 *pcbEncoded
= bytesNeeded
;
1370 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1374 static BOOL WINAPI
CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType
,
1375 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1376 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1382 const CERT_ALT_NAME_INFO
*info
=
1383 (const CERT_ALT_NAME_INFO
*)pvStructInfo
;
1384 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
1387 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1388 * can't encode an erroneous entry index if it's bigger than this.
1390 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1394 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
], NULL
,
1398 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
1400 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1401 * the bad character, now set the index of the bad
1404 *pcbEncoded
= (BYTE
)i
<<
1405 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT
| len
;
1410 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
1411 bytesNeeded
= 1 + lenBytes
+ dataLen
;
1414 *pcbEncoded
= bytesNeeded
;
1419 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1420 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1422 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1423 pbEncoded
= *(BYTE
**)pbEncoded
;
1424 *pbEncoded
++ = ASN_SEQUENCEOF
;
1425 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
1426 pbEncoded
+= lenBytes
;
1427 for (i
= 0; ret
&& i
< info
->cAltEntry
; i
++)
1429 DWORD len
= dataLen
;
1431 ret
= CRYPT_AsnEncodeAltNameEntry(&info
->rgAltEntry
[i
],
1445 SetLastError(STATUS_ACCESS_VIOLATION
);
1452 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType
,
1453 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1454 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1460 const CERT_BASIC_CONSTRAINTS_INFO
*info
=
1461 (const CERT_BASIC_CONSTRAINTS_INFO
*)pvStructInfo
;
1462 struct AsnEncodeSequenceItem items
[3] = {
1463 { &info
->SubjectType
, CRYPT_AsnEncodeBits
, 0 },
1468 if (info
->fPathLenConstraint
)
1470 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1471 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1474 if (info
->cSubtreesConstraint
)
1476 items
[cItem
].pvStructInfo
= &info
->cSubtreesConstraint
;
1477 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
1480 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1481 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1485 SetLastError(STATUS_ACCESS_VIOLATION
);
1492 static BOOL WINAPI
CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType
,
1493 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1494 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1500 const CERT_BASIC_CONSTRAINTS2_INFO
*info
=
1501 (const CERT_BASIC_CONSTRAINTS2_INFO
*)pvStructInfo
;
1502 struct AsnEncodeSequenceItem items
[2] = { { 0 } };
1507 items
[cItem
].pvStructInfo
= &info
->fCA
;
1508 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBool
;
1511 if (info
->fPathLenConstraint
)
1513 items
[cItem
].pvStructInfo
= &info
->dwPathLenConstraint
;
1514 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeInt
;
1517 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
1518 dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1522 SetLastError(STATUS_ACCESS_VIOLATION
);
1529 static BOOL WINAPI
CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType
,
1530 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1531 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1537 const BLOBHEADER
*hdr
=
1538 (const BLOBHEADER
*)pvStructInfo
;
1540 if (hdr
->bType
!= PUBLICKEYBLOB
)
1542 SetLastError(E_INVALIDARG
);
1547 const RSAPUBKEY
*rsaPubKey
= (const RSAPUBKEY
*)
1548 ((const BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
));
1549 CRYPT_INTEGER_BLOB blob
= { rsaPubKey
->bitlen
/ 8,
1550 (BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) };
1551 struct AsnEncodeSequenceItem items
[] = {
1552 { &blob
, CRYPT_AsnEncodeUnsignedInteger
, 0 },
1553 { &rsaPubKey
->pubexp
, CRYPT_AsnEncodeInt
, 0 },
1556 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
1557 sizeof(items
) / sizeof(items
[0]), dwFlags
, pEncodePara
, pbEncoded
,
1563 SetLastError(STATUS_ACCESS_VIOLATION
);
1570 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
1571 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1572 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1578 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
1579 DWORD bytesNeeded
, lenBytes
;
1581 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob
->cbData
, blob
->pbData
,
1582 dwFlags
, pEncodePara
, pbEncoded
, *pcbEncoded
);
1584 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
1585 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
1588 *pcbEncoded
= bytesNeeded
;
1593 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1594 pcbEncoded
, bytesNeeded
)))
1596 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1597 pbEncoded
= *(BYTE
**)pbEncoded
;
1598 *pbEncoded
++ = ASN_OCTETSTRING
;
1599 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
1600 pbEncoded
+= lenBytes
;
1602 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
1608 SetLastError(STATUS_ACCESS_VIOLATION
);
1612 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1616 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
1617 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1618 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1624 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1625 DWORD bytesNeeded
, lenBytes
, dataBytes
;
1628 /* yep, MS allows cUnusedBits to be >= 8 */
1629 if (!blob
->cUnusedBits
)
1631 dataBytes
= blob
->cbData
;
1634 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
1636 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
1637 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
1645 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
1646 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
1649 *pcbEncoded
= bytesNeeded
;
1654 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1655 pcbEncoded
, bytesNeeded
)))
1657 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1658 pbEncoded
= *(BYTE
**)pbEncoded
;
1659 *pbEncoded
++ = ASN_BITSTRING
;
1660 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
1661 pbEncoded
+= lenBytes
;
1662 *pbEncoded
++ = unusedBits
;
1665 BYTE mask
= 0xff << unusedBits
;
1669 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
1670 pbEncoded
+= dataBytes
- 1;
1672 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
1679 SetLastError(STATUS_ACCESS_VIOLATION
);
1686 static BOOL WINAPI
CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType
,
1687 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1688 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1694 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
1695 CRYPT_BIT_BLOB newBlob
= { blob
->cbData
, NULL
, blob
->cUnusedBits
};
1700 newBlob
.pbData
= CryptMemAlloc(newBlob
.cbData
);
1705 for (i
= 0; i
< newBlob
.cbData
; i
++)
1706 newBlob
.pbData
[newBlob
.cbData
- i
- 1] = blob
->pbData
[i
];
1712 ret
= CRYPT_AsnEncodeBits(dwCertEncodingType
, lpszStructType
,
1713 &newBlob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1714 CryptMemFree(newBlob
.pbData
);
1718 SetLastError(STATUS_ACCESS_VIOLATION
);
1725 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
1726 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1727 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1729 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
1731 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
1732 &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1735 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
1736 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1737 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1743 DWORD significantBytes
, lenBytes
;
1744 BYTE padByte
= 0, bytesNeeded
;
1746 const CRYPT_INTEGER_BLOB
*blob
=
1747 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1749 significantBytes
= blob
->cbData
;
1750 if (significantBytes
)
1752 if (blob
->pbData
[significantBytes
- 1] & 0x80)
1754 /* negative, lop off leading (little-endian) 0xffs */
1755 for (; significantBytes
> 0 &&
1756 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
1758 if (blob
->pbData
[significantBytes
- 1] < 0x80)
1766 /* positive, lop off leading (little-endian) zeroes */
1767 for (; significantBytes
> 0 &&
1768 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
1770 if (significantBytes
== 0)
1771 significantBytes
= 1;
1772 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1780 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1782 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1783 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1788 *pcbEncoded
= bytesNeeded
;
1793 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1794 pcbEncoded
, bytesNeeded
)))
1796 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1797 pbEncoded
= *(BYTE
**)pbEncoded
;
1798 *pbEncoded
++ = ASN_INTEGER
;
1801 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1802 pbEncoded
+= lenBytes
;
1803 *pbEncoded
++ = padByte
;
1807 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1808 pbEncoded
+= lenBytes
;
1810 for (; significantBytes
> 0; significantBytes
--)
1811 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1817 SetLastError(STATUS_ACCESS_VIOLATION
);
1824 static BOOL WINAPI
CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType
,
1825 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1826 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1832 DWORD significantBytes
, lenBytes
;
1835 const CRYPT_INTEGER_BLOB
*blob
=
1836 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
1838 significantBytes
= blob
->cbData
;
1839 if (significantBytes
)
1841 /* positive, lop off leading (little-endian) zeroes */
1842 for (; significantBytes
> 0 && !blob
->pbData
[significantBytes
- 1];
1845 if (significantBytes
== 0)
1846 significantBytes
= 1;
1847 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
1851 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
1853 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
1854 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
1859 *pcbEncoded
= bytesNeeded
;
1864 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
1865 pcbEncoded
, bytesNeeded
)))
1867 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1868 pbEncoded
= *(BYTE
**)pbEncoded
;
1869 *pbEncoded
++ = ASN_INTEGER
;
1872 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
1873 pbEncoded
+= lenBytes
;
1878 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
1879 pbEncoded
+= lenBytes
;
1881 for (; significantBytes
> 0; significantBytes
--)
1882 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
1888 SetLastError(STATUS_ACCESS_VIOLATION
);
1895 static BOOL WINAPI
CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType
,
1896 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1897 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1899 CRYPT_INTEGER_BLOB blob
;
1902 /* Encode as an unsigned integer, then change the tag to enumerated */
1903 blob
.cbData
= sizeof(DWORD
);
1904 blob
.pbData
= (BYTE
*)pvStructInfo
;
1905 ret
= CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType
,
1906 X509_MULTI_BYTE_UINT
, &blob
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
1907 if (ret
&& pbEncoded
)
1909 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1910 pbEncoded
= *(BYTE
**)pbEncoded
;
1911 pbEncoded
[0] = ASN_ENUMERATED
;
1916 static BOOL WINAPI
CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType
,
1917 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1918 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1925 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
1926 * temporary buffer because the output buffer is not NULL-terminated.
1929 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1933 *pcbEncoded
= bytesNeeded
;
1938 /* Sanity check the year, this is a two-digit year format */
1939 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1941 if (ret
&& (sysTime
.wYear
< 1950 || sysTime
.wYear
> 2050))
1943 SetLastError(CRYPT_E_BAD_ENCODE
);
1948 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
1949 pbEncoded
, pcbEncoded
, bytesNeeded
)))
1951 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
1952 pbEncoded
= *(BYTE
**)pbEncoded
;
1953 buf
[0] = ASN_UTCTIME
;
1954 buf
[1] = bytesNeeded
- 2;
1955 snprintf(buf
+ 2, sizeof(buf
) - 2,
1956 "%02d%02d%02d%02d%02d%02dZ", sysTime
.wYear
>= 2000 ?
1957 sysTime
.wYear
- 2000 : sysTime
.wYear
- 1900,
1958 sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
1959 sysTime
.wMinute
, sysTime
.wSecond
);
1960 memcpy(pbEncoded
, buf
, bytesNeeded
);
1967 SetLastError(STATUS_ACCESS_VIOLATION
);
1974 static BOOL WINAPI
CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType
,
1975 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
1976 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
1983 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
1984 * temporary buffer because the output buffer is not NULL-terminated.
1987 static const DWORD bytesNeeded
= sizeof(buf
) - 1;
1991 *pcbEncoded
= bytesNeeded
;
1996 ret
= FileTimeToSystemTime((const FILETIME
*)pvStructInfo
,
1999 ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2000 pcbEncoded
, bytesNeeded
);
2003 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2004 pbEncoded
= *(BYTE
**)pbEncoded
;
2005 buf
[0] = ASN_GENERALTIME
;
2006 buf
[1] = bytesNeeded
- 2;
2007 snprintf(buf
+ 2, sizeof(buf
) - 2, "%04d%02d%02d%02d%02d%02dZ",
2008 sysTime
.wYear
, sysTime
.wMonth
, sysTime
.wDay
, sysTime
.wHour
,
2009 sysTime
.wMinute
, sysTime
.wSecond
);
2010 memcpy(pbEncoded
, buf
, bytesNeeded
);
2016 SetLastError(STATUS_ACCESS_VIOLATION
);
2023 static BOOL WINAPI
CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType
,
2024 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2025 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2033 /* Check the year, if it's in the UTCTime range call that encode func */
2034 if (!FileTimeToSystemTime((const FILETIME
*)pvStructInfo
, &sysTime
))
2036 if (sysTime
.wYear
>= 1950 && sysTime
.wYear
<= 2050)
2037 ret
= CRYPT_AsnEncodeUtcTime(dwCertEncodingType
, lpszStructType
,
2038 pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
, pcbEncoded
);
2040 ret
= CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType
,
2041 lpszStructType
, pvStructInfo
, dwFlags
, pEncodePara
, pbEncoded
,
2046 SetLastError(STATUS_ACCESS_VIOLATION
);
2053 static BOOL WINAPI
CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType
,
2054 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2055 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2061 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2062 const CRYPT_SEQUENCE_OF_ANY
*seq
=
2063 (const CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
2065 for (i
= 0, dataLen
= 0; i
< seq
->cValue
; i
++)
2066 dataLen
+= seq
->rgValue
[i
].cbData
;
2067 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2068 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2071 *pcbEncoded
= bytesNeeded
;
2076 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
, pbEncoded
,
2077 pcbEncoded
, bytesNeeded
)))
2079 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2080 pbEncoded
= *(BYTE
**)pbEncoded
;
2081 *pbEncoded
++ = ASN_SEQUENCEOF
;
2082 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2083 pbEncoded
+= lenBytes
;
2084 for (i
= 0; i
< seq
->cValue
; i
++)
2086 memcpy(pbEncoded
, seq
->rgValue
[i
].pbData
,
2087 seq
->rgValue
[i
].cbData
);
2088 pbEncoded
+= seq
->rgValue
[i
].cbData
;
2095 SetLastError(STATUS_ACCESS_VIOLATION
);
2102 static BOOL
CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT
*distPoint
,
2103 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2106 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
2107 struct AsnConstructedItem constructed
= { 0 };
2108 struct AsnEncodeTagSwappedItem swapped
[3] = { { 0 } };
2109 DWORD cItem
= 0, cSwapped
= 0;
2111 switch (distPoint
->DistPointName
.dwDistPointNameChoice
)
2113 case CRL_DIST_POINT_NO_NAME
:
2116 case CRL_DIST_POINT_FULL_NAME
:
2117 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0;
2118 swapped
[cSwapped
].pvStructInfo
= &distPoint
->DistPointName
.u
.FullName
;
2119 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2120 constructed
.tag
= 0;
2121 constructed
.pvStructInfo
= &swapped
[cSwapped
];
2122 constructed
.encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2123 items
[cItem
].pvStructInfo
= &constructed
;
2124 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
2128 case CRL_DIST_POINT_ISSUER_RDN_NAME
:
2129 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2135 if (ret
&& distPoint
->ReasonFlags
.cbData
)
2137 swapped
[cSwapped
].tag
= ASN_CONTEXT
| 1;
2138 swapped
[cSwapped
].pvStructInfo
= &distPoint
->ReasonFlags
;
2139 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeBits
;
2140 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2141 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2145 if (ret
&& distPoint
->CRLIssuer
.cAltEntry
)
2147 swapped
[cSwapped
].tag
= ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2;
2148 swapped
[cSwapped
].pvStructInfo
= &distPoint
->CRLIssuer
;
2149 swapped
[cSwapped
].encodeFunc
= CRYPT_AsnEncodeAltName
;
2150 items
[cItem
].pvStructInfo
= &swapped
[cSwapped
];
2151 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
2156 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, cItem
, 0, NULL
,
2157 pbEncoded
, pcbEncoded
);
2161 static BOOL WINAPI
CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType
,
2162 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2163 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2169 const CRL_DIST_POINTS_INFO
*info
=
2170 (const CRL_DIST_POINTS_INFO
*)pvStructInfo
;
2172 if (!info
->cDistPoint
)
2174 SetLastError(E_INVALIDARG
);
2179 DWORD bytesNeeded
, dataLen
, lenBytes
, i
;
2182 for (i
= 0, dataLen
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2186 ret
= CRYPT_AsnEncodeDistPoint(&info
->rgDistPoint
[i
], NULL
,
2190 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING
)
2192 /* Have to propagate index of failing character */
2198 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
2199 bytesNeeded
= 1 + lenBytes
+ dataLen
;
2202 *pcbEncoded
= bytesNeeded
;
2207 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2208 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2210 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2211 pbEncoded
= *(BYTE
**)pbEncoded
;
2212 *pbEncoded
++ = ASN_SEQUENCEOF
;
2213 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
2214 pbEncoded
+= lenBytes
;
2215 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2217 DWORD len
= dataLen
;
2219 ret
= CRYPT_AsnEncodeDistPoint(
2220 &info
->rgDistPoint
[i
], pbEncoded
, &len
);
2234 SetLastError(STATUS_ACCESS_VIOLATION
);
2241 static BOOL WINAPI
CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
2242 LPCSTR lpszStructType
, const void *pvStructInfo
, DWORD dwFlags
,
2243 PCRYPT_ENCODE_PARA pEncodePara
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
2249 const CERT_ENHKEY_USAGE
*usage
=
2250 (const CERT_ENHKEY_USAGE
*)pvStructInfo
;
2251 DWORD bytesNeeded
= 0, lenBytes
, size
, i
;
2254 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2256 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2257 usage
->rgpszUsageIdentifier
[i
],
2258 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &size
);
2260 bytesNeeded
+= size
;
2262 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
2263 bytesNeeded
+= 1 + lenBytes
;
2267 *pcbEncoded
= bytesNeeded
;
2270 if ((ret
= CRYPT_EncodeEnsureSpace(dwFlags
, pEncodePara
,
2271 pbEncoded
, pcbEncoded
, bytesNeeded
)))
2273 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
)
2274 pbEncoded
= *(BYTE
**)pbEncoded
;
2275 *pbEncoded
++ = ASN_SEQUENCEOF
;
2276 CRYPT_EncodeLen(bytesNeeded
- lenBytes
- 1, pbEncoded
,
2278 pbEncoded
+= lenBytes
;
2279 for (i
= 0; ret
&& i
< usage
->cUsageIdentifier
; i
++)
2282 ret
= CRYPT_AsnEncodeOid(dwCertEncodingType
, NULL
,
2283 usage
->rgpszUsageIdentifier
[i
],
2284 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pbEncoded
,
2289 bytesNeeded
-= size
;
2298 SetLastError(STATUS_ACCESS_VIOLATION
);
2305 BOOL WINAPI
CryptEncodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2306 const void *pvStructInfo
, DWORD dwFlags
, PCRYPT_ENCODE_PARA pEncodePara
,
2307 void *pvEncoded
, DWORD
*pcbEncoded
)
2309 static HCRYPTOIDFUNCSET set
= NULL
;
2311 CryptEncodeObjectExFunc encodeFunc
= NULL
;
2312 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2314 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType
,
2315 debugstr_a(lpszStructType
), pvStructInfo
, dwFlags
, pEncodePara
,
2316 pvEncoded
, pcbEncoded
);
2318 if (!pvEncoded
&& !pcbEncoded
)
2320 SetLastError(ERROR_INVALID_PARAMETER
);
2323 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
2324 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
2326 SetLastError(ERROR_FILE_NOT_FOUND
);
2330 SetLastError(NOERROR
);
2331 if (dwFlags
& CRYPT_ENCODE_ALLOC_FLAG
&& pvEncoded
)
2332 *(BYTE
**)pvEncoded
= NULL
;
2333 if (!HIWORD(lpszStructType
))
2335 switch (LOWORD(lpszStructType
))
2337 case (WORD
)X509_CERT
:
2338 encodeFunc
= CRYPT_AsnEncodeCert
;
2340 case (WORD
)X509_CERT_TO_BE_SIGNED
:
2341 encodeFunc
= CRYPT_AsnEncodeCertInfo
;
2343 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
2344 encodeFunc
= CRYPT_AsnEncodeCRLInfo
;
2346 case (WORD
)X509_EXTENSIONS
:
2347 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2349 case (WORD
)X509_NAME
:
2350 encodeFunc
= CRYPT_AsnEncodeName
;
2352 case (WORD
)X509_PUBLIC_KEY_INFO
:
2353 encodeFunc
= CRYPT_AsnEncodePubKeyInfo
;
2355 case (WORD
)X509_ALTERNATE_NAME
:
2356 encodeFunc
= CRYPT_AsnEncodeAltName
;
2358 case (WORD
)X509_BASIC_CONSTRAINTS
:
2359 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2361 case (WORD
)X509_BASIC_CONSTRAINTS2
:
2362 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2364 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
2365 encodeFunc
= CRYPT_AsnEncodeRsaPubKey
;
2367 case (WORD
)X509_OCTET_STRING
:
2368 encodeFunc
= CRYPT_AsnEncodeOctets
;
2370 case (WORD
)X509_BITS
:
2371 case (WORD
)X509_KEY_USAGE
:
2372 encodeFunc
= CRYPT_AsnEncodeBits
;
2374 case (WORD
)X509_INTEGER
:
2375 encodeFunc
= CRYPT_AsnEncodeInt
;
2377 case (WORD
)X509_MULTI_BYTE_INTEGER
:
2378 encodeFunc
= CRYPT_AsnEncodeInteger
;
2380 case (WORD
)X509_MULTI_BYTE_UINT
:
2381 encodeFunc
= CRYPT_AsnEncodeUnsignedInteger
;
2383 case (WORD
)X509_ENUMERATED
:
2384 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2386 case (WORD
)X509_CHOICE_OF_TIME
:
2387 encodeFunc
= CRYPT_AsnEncodeChoiceOfTime
;
2389 case (WORD
)X509_SEQUENCE_OF_ANY
:
2390 encodeFunc
= CRYPT_AsnEncodeSequenceOfAny
;
2392 case (WORD
)PKCS_UTC_TIME
:
2393 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2395 case (WORD
)X509_CRL_DIST_POINTS
:
2396 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2398 case (WORD
)X509_ENHANCED_KEY_USAGE
:
2399 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2402 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
2405 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
2406 encodeFunc
= CRYPT_AsnEncodeExtensions
;
2407 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
2408 encodeFunc
= CRYPT_AsnEncodeUtcTime
;
2409 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
2410 encodeFunc
= CRYPT_AsnEncodeEnumerated
;
2411 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2412 encodeFunc
= CRYPT_AsnEncodeBits
;
2413 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
2414 encodeFunc
= CRYPT_AsnEncodeOctets
;
2415 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
2416 encodeFunc
= CRYPT_AsnEncodeBasicConstraints
;
2417 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2418 encodeFunc
= CRYPT_AsnEncodeBasicConstraints2
;
2419 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2420 encodeFunc
= CRYPT_AsnEncodeAltName
;
2421 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2422 encodeFunc
= CRYPT_AsnEncodeAltName
;
2423 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
2424 encodeFunc
= CRYPT_AsnEncodeAltName
;
2425 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2426 encodeFunc
= CRYPT_AsnEncodeAltName
;
2427 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2428 encodeFunc
= CRYPT_AsnEncodeAltName
;
2429 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2430 encodeFunc
= CRYPT_AsnEncodeCRLDistPoints
;
2431 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2432 encodeFunc
= CRYPT_AsnEncodeEnhancedKeyUsage
;
2434 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2435 debugstr_a(lpszStructType
));
2439 set
= CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC
, 0);
2440 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2441 (void **)&encodeFunc
, &hFunc
);
2444 ret
= encodeFunc(dwCertEncodingType
, lpszStructType
, pvStructInfo
,
2445 dwFlags
, pEncodePara
, pvEncoded
, pcbEncoded
);
2447 SetLastError(ERROR_FILE_NOT_FOUND
);
2449 CryptFreeOIDFunctionAddress(hFunc
, 0);
2453 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
2454 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
2455 DWORD
*pcbStructInfo
)
2457 static HCRYPTOIDFUNCSET set
= NULL
;
2459 CryptDecodeObjectFunc pCryptDecodeObject
;
2460 HCRYPTOIDFUNCADDR hFunc
;
2462 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType
,
2463 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
2464 pvStructInfo
, pcbStructInfo
);
2466 if (!pvStructInfo
&& !pcbStructInfo
)
2468 SetLastError(ERROR_INVALID_PARAMETER
);
2472 /* Try registered DLL first.. */
2474 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
2475 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2476 (void **)&pCryptDecodeObject
, &hFunc
);
2477 if (pCryptDecodeObject
)
2479 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
2480 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
2481 CryptFreeOIDFunctionAddress(hFunc
, 0);
2485 /* If not, use CryptDecodeObjectEx */
2486 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
2487 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
2492 /* Gets the number of length bytes from the given (leading) length byte */
2493 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
2495 /* Helper function to get the encoded length of the data starting at pbEncoded,
2496 * where pbEncoded[0] is the tag. If the data are too short to contain a
2497 * length or if the length is too large for cbEncoded, sets an appropriate
2498 * error code and returns FALSE.
2500 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2507 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2510 else if (pbEncoded
[1] <= 0x7f)
2512 if (pbEncoded
[1] + 1 > cbEncoded
)
2514 SetLastError(CRYPT_E_ASN1_EOD
);
2519 *len
= pbEncoded
[1];
2525 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
2527 if (lenLen
> sizeof(DWORD
) + 1)
2529 SetLastError(CRYPT_E_ASN1_LARGE
);
2532 else if (lenLen
+ 2 > cbEncoded
)
2534 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2545 out
|= *pbEncoded
++;
2547 if (out
+ lenLen
+ 1 > cbEncoded
)
2549 SetLastError(CRYPT_E_ASN1_EOD
);
2562 /* Helper function to check *pcbStructInfo, set it to the required size, and
2563 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
2564 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
2565 * pointer to the newly allocated memory.
2567 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
2568 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2573 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2575 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
2576 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
2578 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
2579 if (!*(BYTE
**)pvStructInfo
)
2582 *pcbStructInfo
= bytesNeeded
;
2584 else if (*pcbStructInfo
< bytesNeeded
)
2586 *pcbStructInfo
= bytesNeeded
;
2587 SetLastError(ERROR_MORE_DATA
);
2594 * The expected tag of the item. If tag is 0, decodeFunc is called
2595 * regardless of the tag value seen.
2597 * A sequence is decoded into a struct. The offset member is the
2598 * offset of this item within that struct.
2600 * The decoder function to use. If this is NULL, then the member isn't
2601 * decoded, but minSize space is reserved for it.
2603 * The minimum amount of space occupied after decoding. You must set this.
2605 * If true, and the tag doesn't match the expected tag for this item,
2606 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
2607 * filled with 0 for this member.
2608 * hasPointer, pointerOffset, minSize:
2609 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
2610 * the offset within the (outer) struct of the data pointer (or to the
2611 * first data pointer, if more than one exist).
2613 * Used by CRYPT_AsnDecodeSequence, not for your use.
2615 struct AsnDecodeSequenceItem
2619 CryptDecodeObjectExFunc decodeFunc
;
2623 DWORD pointerOffset
;
2627 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
2628 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2629 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
)
2635 ptr
= pbEncoded
+ 1 + GET_LEN_BYTES(pbEncoded
[1]);
2636 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
2638 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2642 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2645 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2647 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
2649 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
2651 TRACE("Setting next pointer to %p\n",
2653 *(BYTE
**)((BYTE
*)pvStructInfo
+
2654 items
[i
].pointerOffset
) = nextData
;
2656 if (items
[i
].decodeFunc
)
2659 TRACE("decoding item %ld\n", i
);
2661 TRACE("sizing item %ld\n", i
);
2662 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
2663 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
2664 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2665 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
2666 : NULL
, &items
[i
].size
);
2669 if (nextData
&& items
[i
].hasPointer
&&
2670 items
[i
].size
> items
[i
].minSize
)
2672 nextData
+= items
[i
].size
- items
[i
].minSize
;
2673 /* align nextData to DWORD boundaries */
2674 if (items
[i
].size
% sizeof(DWORD
))
2675 nextData
+= sizeof(DWORD
) - items
[i
].size
%
2678 /* Account for alignment padding */
2679 if (items
[i
].size
% sizeof(DWORD
))
2680 items
[i
].size
+= sizeof(DWORD
) -
2681 items
[i
].size
% sizeof(DWORD
);
2682 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
2684 else if (items
[i
].optional
&&
2685 GetLastError() == CRYPT_E_ASN1_BADTAG
)
2687 TRACE("skipping optional item %ld\n", i
);
2688 items
[i
].size
= items
[i
].minSize
;
2689 SetLastError(NOERROR
);
2693 TRACE("item %ld failed: %08lx\n", i
,
2697 items
[i
].size
= items
[i
].minSize
;
2699 else if (items
[i
].optional
)
2701 TRACE("skipping optional item %ld\n", i
);
2702 items
[i
].size
= items
[i
].minSize
;
2706 TRACE("tag %02x doesn't match expected %02x\n",
2707 ptr
[0], items
[i
].tag
);
2708 SetLastError(CRYPT_E_ASN1_BADTAG
);
2713 else if (items
[i
].optional
)
2715 TRACE("missing optional item %ld, skipping\n", i
);
2716 items
[i
].size
= items
[i
].minSize
;
2720 TRACE("not enough bytes for item %ld, failing\n", i
);
2721 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2725 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
2727 TRACE("%ld remaining bytes, failing\n", cbEncoded
-
2729 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2735 /* This decodes an arbitrary sequence into a contiguous block of memory
2736 * (basically, a struct.) Each element being decoded is described by a struct
2737 * AsnDecodeSequenceItem, see above.
2738 * startingPointer is an optional pointer to the first place where dynamic
2739 * data will be stored. If you know the starting offset, you may pass it
2740 * here. Otherwise, pass NULL, and one will be inferred from the items.
2741 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
2742 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
2744 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
2745 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
2746 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2747 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
2751 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
2752 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2755 if (pbEncoded
[0] == ASN_SEQUENCE
)
2759 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2763 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, pbEncoded
,
2764 cbEncoded
, dwFlags
, NULL
, NULL
);
2767 DWORD bytesNeeded
= 0, structSize
= 0;
2769 for (i
= 0; i
< cItem
; i
++)
2771 bytesNeeded
+= items
[i
].size
;
2772 structSize
+= items
[i
].minSize
;
2775 *pcbStructInfo
= bytesNeeded
;
2776 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2777 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2781 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2782 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2783 if (startingPointer
)
2784 nextData
= (BYTE
*)startingPointer
;
2786 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
2787 memset(pvStructInfo
, 0, structSize
);
2788 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
2789 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
);
2796 SetLastError(CRYPT_E_ASN1_BADTAG
);
2799 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2804 * The expected tag of the entire encoded array (usually a variant
2805 * of ASN_SETOF or ASN_SEQUENCEOF.)
2807 * used to decode each item in the array
2809 * is the minimum size of each decoded item
2811 * indicates whether each item has a dynamic pointer
2813 * indicates the offset within itemSize at which the pointer exists
2815 struct AsnArrayDescriptor
2818 CryptDecodeObjectExFunc decodeFunc
;
2821 DWORD pointerOffset
;
2824 struct AsnArrayItemSize
2830 /* Decodes an array of like types into a struct GenericArray.
2831 * The layout and decoding of the array are described by a struct
2832 * AsnArrayDescriptor.
2834 static BOOL
CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor
*arrayDesc
,
2835 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2836 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2837 void *startingPointer
)
2841 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc
, pbEncoded
,
2842 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
2845 if (pbEncoded
[0] == arrayDesc
->tag
)
2849 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2851 DWORD bytesNeeded
, cItems
= 0;
2852 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2853 /* There can be arbitrarily many items, but there is often only one.
2855 struct AsnArrayItemSize itemSize
= { 0 }, *itemSizes
= &itemSize
;
2857 bytesNeeded
= sizeof(struct GenericArray
);
2862 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2863 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
2865 DWORD itemLenBytes
, itemDataLen
, size
;
2867 itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
2868 /* Each item decoded may not tolerate extraneous bytes, so
2869 * get the length of the next element and pass it directly.
2871 ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
2874 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
2875 1 + itemLenBytes
+ itemDataLen
,
2876 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
2883 if (itemSizes
!= &itemSize
)
2884 itemSizes
= CryptMemRealloc(itemSizes
,
2885 cItems
* sizeof(struct AsnArrayItemSize
));
2890 cItems
* sizeof(struct AsnArrayItemSize
));
2891 memcpy(itemSizes
, &itemSize
, sizeof(itemSize
));
2895 itemSizes
[cItems
- 1].encodedLen
= 1 + itemLenBytes
2897 itemSizes
[cItems
- 1].size
= size
;
2898 bytesNeeded
+= size
;
2899 ret
= CRYPT_GetLen(ptr
,
2900 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2902 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2912 *pcbStructInfo
= bytesNeeded
;
2913 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
2914 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2919 struct GenericArray
*array
;
2921 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2922 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2923 array
= (struct GenericArray
*)pvStructInfo
;
2924 array
->cItems
= cItems
;
2925 if (startingPointer
)
2926 array
->rgItems
= startingPointer
;
2928 array
->rgItems
= (BYTE
*)array
+
2929 sizeof(struct GenericArray
);
2930 nextData
= (BYTE
*)array
->rgItems
+
2931 array
->cItems
* arrayDesc
->itemSize
;
2932 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
2933 i
< cItems
&& ptr
- pbEncoded
- 1 - lenBytes
<
2936 if (arrayDesc
->hasPointer
)
2937 *(BYTE
**)(array
->rgItems
+ i
* arrayDesc
->itemSize
2938 + arrayDesc
->pointerOffset
) = nextData
;
2939 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
2940 itemSizes
[i
].encodedLen
,
2941 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
2942 array
->rgItems
+ i
* arrayDesc
->itemSize
,
2943 &itemSizes
[i
].size
);
2948 nextData
+= itemSizes
[i
].size
- arrayDesc
->itemSize
;
2949 ret
= CRYPT_GetLen(ptr
,
2950 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
2952 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
2957 if (itemSizes
!= &itemSize
)
2958 CryptMemFree(itemSizes
);
2963 SetLastError(CRYPT_E_ASN1_BADTAG
);
2969 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
2970 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
2971 * to CRYPT_E_ASN1_CORRUPT.
2972 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
2975 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
2976 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2977 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2982 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2984 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2985 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
2987 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
2988 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
2991 *pcbStructInfo
= bytesNeeded
;
2992 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2993 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2995 CRYPT_DER_BLOB
*blob
;
2997 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2998 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2999 blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
3000 blob
->cbData
= 1 + lenBytes
+ dataLen
;
3003 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3004 blob
->pbData
= (BYTE
*)pbEncoded
;
3007 assert(blob
->pbData
);
3008 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3013 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3021 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
3022 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
3023 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3024 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3028 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
3029 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3031 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3034 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
3035 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
3036 pvStructInfo
, pcbStructInfo
);
3037 if (ret
&& pvStructInfo
)
3039 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
3046 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
3048 temp
= blob
->pbData
[i
];
3049 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
3050 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
3054 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3058 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
3059 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3060 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3064 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3065 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3069 struct AsnDecodeSequenceItem items
[] = {
3070 { 0, offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
3071 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
3072 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
3073 { ASN_SEQUENCEOF
, offsetof(CERT_SIGNED_CONTENT_INFO
,
3074 SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
3075 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
,
3076 offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
3077 { ASN_BITSTRING
, offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
3078 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
3079 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
3082 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
3083 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
3084 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3085 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3086 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3090 SetLastError(STATUS_ACCESS_VIOLATION
);
3097 /* Internal function */
3098 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
3099 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3100 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3105 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3107 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3109 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
3110 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
3111 pvStructInfo
, pcbStructInfo
);
3116 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
3117 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3118 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3122 struct AsnDecodeSequenceItem items
[] = {
3123 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
3124 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3125 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
3126 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3129 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3130 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3131 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3135 /* Internal function */
3136 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
3137 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3138 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3143 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3145 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3147 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3148 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
3149 pDecodePara
, pvStructInfo
, pcbStructInfo
);
3154 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
3155 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3156 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3160 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3161 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3165 struct AsnDecodeSequenceItem items
[] = {
3166 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CERT_INFO
, dwVersion
),
3167 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3168 { ASN_INTEGER
, offsetof(CERT_INFO
, SerialNumber
),
3169 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
3170 TRUE
, offsetof(CERT_INFO
, SerialNumber
.pbData
), 0 },
3171 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SignatureAlgorithm
),
3172 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3173 FALSE
, TRUE
, offsetof(CERT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
3174 { 0, offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3175 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
3177 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, NotBefore
),
3178 CRYPT_AsnDecodeValidity
, sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
,
3180 { 0, offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
3181 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
3183 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SubjectPublicKeyInfo
),
3184 CRYPT_AsnDecodePubKeyInfoInternal
, sizeof(CERT_PUBLIC_KEY_INFO
),
3185 FALSE
, TRUE
, offsetof(CERT_INFO
,
3186 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
3187 { ASN_BITSTRING
, offsetof(CERT_INFO
, IssuerUniqueId
),
3188 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3189 offsetof(CERT_INFO
, IssuerUniqueId
.pbData
), 0 },
3190 { ASN_BITSTRING
, offsetof(CERT_INFO
, SubjectUniqueId
),
3191 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3192 offsetof(CERT_INFO
, SubjectUniqueId
.pbData
), 0 },
3193 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3, offsetof(CERT_INFO
, cExtension
),
3194 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
3195 offsetof(CERT_INFO
, rgExtension
), 0 },
3198 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3199 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3200 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3204 SetLastError(STATUS_ACCESS_VIOLATION
);
3211 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType
,
3212 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3213 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3216 struct AsnDecodeSequenceItem items
[] = {
3217 { ASN_INTEGER
, offsetof(CRL_ENTRY
, SerialNumber
),
3218 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
,
3219 offsetof(CRL_ENTRY
, SerialNumber
.pbData
), 0 },
3220 { 0, offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
3221 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3222 { ASN_SEQUENCEOF
, offsetof(CRL_ENTRY
, cExtension
),
3223 CRYPT_AsnDecodeExtensionsInternal
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
3224 offsetof(CRL_ENTRY
, rgExtension
), 0 },
3226 PCRL_ENTRY entry
= (PCRL_ENTRY
)pvStructInfo
;
3228 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
3231 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3232 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3233 NULL
, entry
, pcbStructInfo
, entry
? entry
->SerialNumber
.pbData
: NULL
);
3237 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
3238 * been set prior to calling.
3240 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
3241 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3242 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3245 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3246 CRYPT_AsnDecodeCRLEntry
, sizeof(CRL_ENTRY
), TRUE
,
3247 offsetof(CRL_ENTRY
, SerialNumber
.pbData
) };
3248 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
3250 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3251 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3253 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3254 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3255 entries
? entries
->rgItems
: NULL
);
3256 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3260 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
3261 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3262 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3266 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3267 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3271 struct AsnDecodeSequenceItem items
[] = {
3272 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CRL_INFO
, dwVersion
),
3273 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
3274 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, SignatureAlgorithm
),
3275 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3276 FALSE
, TRUE
, offsetof(CRL_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
3277 { 0, offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3278 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
3280 { 0, offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3281 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
3282 { 0, offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
3283 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
3284 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, cCRLEntry
),
3285 CRYPT_AsnDecodeCRLEntries
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3286 offsetof(CRL_INFO
, rgCRLEntry
), 0 },
3287 /* Note that the extensions are ignored by MS, so I'll ignore them too
3289 { 0, offsetof(CRL_INFO
, cExtension
), NULL
,
3290 sizeof(CERT_EXTENSIONS
), TRUE
, FALSE
, 0 },
3293 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3294 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3295 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3299 SetLastError(STATUS_ACCESS_VIOLATION
);
3304 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
3308 static BOOL WINAPI
CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType
,
3309 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3310 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3314 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3315 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3317 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
3321 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3323 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3324 DWORD bytesNeeded
= sizeof(LPSTR
);
3328 /* The largest possible string for the first two components
3329 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
3334 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
3335 pbEncoded
[1 + lenBytes
] / 40,
3336 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
3338 bytesNeeded
+= strlen(firstTwo
) + 1;
3339 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3340 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3342 /* large enough for ".4000000" */
3346 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3353 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
3356 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3363 snprintf(str
, sizeof(str
), ".%d", val
);
3364 bytesNeeded
+= strlen(str
);
3369 *pcbStructInfo
= bytesNeeded
;
3370 else if (*pcbStructInfo
< bytesNeeded
)
3372 *pcbStructInfo
= bytesNeeded
;
3373 SetLastError(ERROR_MORE_DATA
);
3381 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
3384 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
3385 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
3387 pszObjId
+= strlen(pszObjId
);
3388 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
3389 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
3393 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
3402 sprintf(pszObjId
, ".%d", val
);
3403 pszObjId
+= strlen(pszObjId
);
3407 *(LPSTR
*)pvStructInfo
= NULL
;
3408 *pcbStructInfo
= bytesNeeded
;
3415 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
3418 static BOOL WINAPI
CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType
,
3419 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3420 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3422 struct AsnDecodeSequenceItem items
[] = {
3423 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_EXTENSION
, pszObjId
),
3424 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), FALSE
, TRUE
,
3425 offsetof(CERT_EXTENSION
, pszObjId
), 0 },
3426 { ASN_BOOL
, offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
3427 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
3428 { ASN_OCTETSTRING
, offsetof(CERT_EXTENSION
, Value
),
3429 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
,
3430 offsetof(CERT_EXTENSION
, Value
.pbData
) },
3433 PCERT_EXTENSION ext
= (PCERT_EXTENSION
)pvStructInfo
;
3435 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
3439 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
3440 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3441 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3442 ext
, pcbStructInfo
, ext
? ext
->pszObjId
: NULL
);
3444 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
3445 debugstr_a(ext
->pszObjId
));
3446 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3450 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
3451 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3452 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3455 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3456 CRYPT_AsnDecodeExtension
, sizeof(CERT_EXTENSION
), TRUE
,
3457 offsetof(CERT_EXTENSION
, pszObjId
) };
3458 PCERT_EXTENSIONS exts
= (PCERT_EXTENSIONS
)pvStructInfo
;
3460 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3461 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3463 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3464 pDecodePara
, pvStructInfo
, pcbStructInfo
, exts
? exts
->rgExtension
: NULL
);
3468 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
3469 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3470 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3476 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3477 lpszStructType
, pbEncoded
, cbEncoded
,
3478 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3479 if (ret
&& pvStructInfo
)
3481 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3482 pcbStructInfo
, *pcbStructInfo
);
3485 CERT_EXTENSIONS
*exts
;
3487 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3488 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3489 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
3490 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
3491 sizeof(CERT_EXTENSIONS
));
3492 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
3493 lpszStructType
, pbEncoded
, cbEncoded
,
3494 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3501 SetLastError(STATUS_ACCESS_VIOLATION
);
3508 /* Warning: this assumes the address of value->Value.pbData is already set, in
3509 * order to avoid overwriting memory. (In some cases, it may change it, if it
3510 * doesn't copy anything to memory.) Be sure to set it correctly!
3512 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
3513 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3514 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3521 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
3523 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3525 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3527 switch (pbEncoded
[0])
3529 case ASN_NUMERICSTRING
:
3530 case ASN_PRINTABLESTRING
:
3534 FIXME("Unimplemented string type %02x\n", pbEncoded
[0]);
3535 SetLastError(OSS_UNIMPLEMENTED
);
3540 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
);
3542 switch (pbEncoded
[0])
3544 case ASN_NUMERICSTRING
:
3545 case ASN_PRINTABLESTRING
:
3547 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3548 bytesNeeded
+= dataLen
;
3552 *pcbStructInfo
= bytesNeeded
;
3553 else if (*pcbStructInfo
< bytesNeeded
)
3555 *pcbStructInfo
= bytesNeeded
;
3556 SetLastError(ERROR_MORE_DATA
);
3561 *pcbStructInfo
= bytesNeeded
;
3562 switch (pbEncoded
[0])
3564 case ASN_NUMERICSTRING
:
3565 value
->dwValueType
= CERT_RDN_NUMERIC_STRING
;
3567 case ASN_PRINTABLESTRING
:
3568 value
->dwValueType
= CERT_RDN_PRINTABLE_STRING
;
3571 value
->dwValueType
= CERT_RDN_IA5_STRING
;
3576 switch (pbEncoded
[0])
3578 case ASN_NUMERICSTRING
:
3579 case ASN_PRINTABLESTRING
:
3581 value
->Value
.cbData
= dataLen
;
3582 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3583 value
->Value
.pbData
= (BYTE
*)pbEncoded
+ 1 +
3587 assert(value
->Value
.pbData
);
3588 memcpy(value
->Value
.pbData
,
3589 pbEncoded
+ 1 + lenBytes
, dataLen
);
3596 value
->Value
.cbData
= 0;
3597 value
->Value
.pbData
= NULL
;
3605 SetLastError(STATUS_ACCESS_VIOLATION
);
3612 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType
,
3613 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3614 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3618 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3619 pvStructInfo
, *pcbStructInfo
);
3623 struct AsnDecodeSequenceItem items
[] = {
3624 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
3625 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), FALSE
, TRUE
,
3626 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
3627 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
), CRYPT_AsnDecodeNameValue
,
3628 sizeof(CERT_NAME_VALUE
), FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
,
3631 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
3634 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
3635 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3636 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
3637 attr
, pcbStructInfo
, attr
? attr
->pszObjId
: NULL
);
3640 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
3641 debugstr_a(attr
->pszObjId
));
3642 TRACE("attr->dwValueType is %ld\n", attr
->dwValueType
);
3644 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3648 SetLastError(STATUS_ACCESS_VIOLATION
);
3655 static BOOL WINAPI
CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType
,
3656 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3657 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3663 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
3664 CRYPT_AsnDecodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
3665 offsetof(CERT_RDN_ATTR
, pszObjId
) };
3666 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
3668 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3669 pDecodePara
, pvStructInfo
, pcbStructInfo
, rdn
? rdn
->rgRDNAttr
: NULL
);
3673 SetLastError(STATUS_ACCESS_VIOLATION
);
3680 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
3681 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3682 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3688 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3689 CRYPT_AsnDecodeRdn
, sizeof(CERT_RDN
), TRUE
,
3690 offsetof(CERT_RDN
, rgRDNAttr
) };
3692 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3693 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3697 SetLastError(STATUS_ACCESS_VIOLATION
);
3704 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
3705 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3706 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3709 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
3711 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3712 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3714 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3715 bytesNeeded
+= cbEncoded
;
3717 *pcbStructInfo
= bytesNeeded
;
3718 else if (*pcbStructInfo
< bytesNeeded
)
3720 SetLastError(ERROR_MORE_DATA
);
3721 *pcbStructInfo
= bytesNeeded
;
3726 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
3728 *pcbStructInfo
= bytesNeeded
;
3729 blob
->cbData
= cbEncoded
;
3730 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3731 blob
->pbData
= (LPBYTE
)pbEncoded
;
3734 assert(blob
->pbData
);
3735 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
3741 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
3742 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3743 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3745 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
3746 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
3748 struct AsnDecodeSequenceItem items
[] = {
3749 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
3750 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), FALSE
, TRUE
,
3751 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
3752 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
3753 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
3754 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
3757 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3758 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3760 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3761 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3762 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
3763 if (ret
&& pvStructInfo
)
3765 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
3766 debugstr_a(algo
->pszObjId
));
3771 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
3772 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3773 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3776 struct AsnDecodeSequenceItem items
[] = {
3777 { ASN_SEQUENCEOF
, offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
3778 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3779 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
3780 Algorithm
.pszObjId
) },
3781 { ASN_BITSTRING
, offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
3782 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
3783 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
3785 PCERT_PUBLIC_KEY_INFO info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
3787 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3788 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3789 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
?
3790 info
->Algorithm
.Parameters
.pbData
: NULL
);
3794 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
3795 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3796 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3804 if ((ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
3805 lpszStructType
, pbEncoded
, cbEncoded
,
3806 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
3809 *pcbStructInfo
= bytesNeeded
;
3810 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3811 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3813 PCERT_PUBLIC_KEY_INFO info
;
3815 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3816 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3817 info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
3818 info
->Algorithm
.Parameters
.pbData
= (BYTE
*)pvStructInfo
+
3819 sizeof(CERT_PUBLIC_KEY_INFO
);
3820 ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
3821 lpszStructType
, pbEncoded
, cbEncoded
,
3822 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3829 SetLastError(STATUS_ACCESS_VIOLATION
);
3836 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
3837 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3838 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3844 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3847 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
3849 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3852 if (pbEncoded
[1] > 1)
3854 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3859 *pcbStructInfo
= sizeof(BOOL
);
3862 else if (*pcbStructInfo
< sizeof(BOOL
))
3864 *pcbStructInfo
= sizeof(BOOL
);
3865 SetLastError(ERROR_MORE_DATA
);
3870 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
3873 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
3877 static BOOL WINAPI
CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType
,
3878 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3879 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3881 PCERT_ALT_NAME_ENTRY entry
= (PCERT_ALT_NAME_ENTRY
)pvStructInfo
;
3882 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
3885 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3886 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3890 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3893 if ((pbEncoded
[0] & ASN_FLAGS_MASK
) != ASN_CONTEXT
)
3895 SetLastError(CRYPT_E_ASN1_BADTAG
);
3898 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3899 if (1 + lenBytes
> cbEncoded
)
3901 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3904 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3906 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
3908 case 1: /* rfc822Name */
3909 case 2: /* dNSName */
3910 case 6: /* uniformResourceIdentifier */
3911 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
3913 case 7: /* iPAddress */
3914 bytesNeeded
+= dataLen
;
3916 case 8: /* registeredID */
3917 /* FIXME: decode as OID */
3918 case 0: /* otherName */
3919 case 4: /* directoryName */
3921 SetLastError(CRYPT_E_ASN1_BADTAG
);
3924 case 3: /* x400Address, unimplemented */
3925 case 5: /* ediPartyName, unimplemented */
3926 SetLastError(CRYPT_E_ASN1_BADTAG
);
3930 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3936 *pcbStructInfo
= bytesNeeded
;
3937 else if (*pcbStructInfo
< bytesNeeded
)
3939 *pcbStructInfo
= bytesNeeded
;
3940 SetLastError(ERROR_MORE_DATA
);
3945 *pcbStructInfo
= bytesNeeded
;
3946 /* MS used values one greater than the asn1 ones.. sigh */
3947 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
3948 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
3950 case 1: /* rfc822Name */
3951 case 2: /* dNSName */
3952 case 6: /* uniformResourceIdentifier */
3956 for (i
= 0; i
< dataLen
; i
++)
3957 entry
->u
.pwszURL
[i
] =
3958 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
3959 entry
->u
.pwszURL
[i
] = 0;
3960 TRACE("URL is %p (%s)\n", entry
->u
.pwszURL
,
3961 debugstr_w(entry
->u
.pwszURL
));
3964 case 7: /* iPAddress */
3965 /* The next data pointer is in the pwszURL spot, that is,
3966 * the first 4 bytes. Need to move it to the next spot.
3968 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
3969 entry
->u
.IPAddress
.cbData
= dataLen
;
3970 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
3980 static BOOL WINAPI
CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType
,
3981 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3982 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3985 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3986 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
3987 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
3988 PCERT_ALT_NAME_INFO info
= (PCERT_ALT_NAME_INFO
)pvStructInfo
;
3990 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
3991 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3994 TRACE("info->rgAltEntry is %p\n", info
->rgAltEntry
);
3995 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3996 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->rgAltEntry
: NULL
);
4000 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
4001 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4002 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4006 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4007 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4011 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
4012 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
4013 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
4015 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4016 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4020 SetLastError(STATUS_ACCESS_VIOLATION
);
4027 struct PATH_LEN_CONSTRAINT
4029 BOOL fPathLenConstraint
;
4030 DWORD dwPathLenConstraint
;
4033 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
4034 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4035 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4039 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4040 pvStructInfo
, *pcbStructInfo
);
4044 if (pbEncoded
[0] == ASN_INTEGER
)
4046 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
4049 *pcbStructInfo
= bytesNeeded
;
4050 else if (*pcbStructInfo
< bytesNeeded
)
4052 SetLastError(ERROR_MORE_DATA
);
4053 *pcbStructInfo
= bytesNeeded
;
4058 struct PATH_LEN_CONSTRAINT
*constraint
=
4059 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
4060 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
4062 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
4063 pbEncoded
, cbEncoded
, 0, NULL
,
4064 &constraint
->dwPathLenConstraint
, &size
);
4066 constraint
->fPathLenConstraint
= TRUE
;
4067 TRACE("got an int, dwPathLenConstraint is %ld\n",
4068 constraint
->dwPathLenConstraint
);
4073 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4077 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4081 static BOOL WINAPI
CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType
,
4082 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4083 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4086 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
4087 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
4088 offsetof(CERT_NAME_BLOB
, pbData
) };
4089 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
4091 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4092 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4094 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4095 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4096 entries
? entries
->rgItems
: NULL
);
4097 TRACE("Returning %d (%08lx)\n", ret
, GetLastError());
4101 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
4102 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4103 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4109 struct AsnDecodeSequenceItem items
[] = {
4110 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
4111 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
4112 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
4113 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
4114 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
4115 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
4116 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
4117 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
4118 sizeof(struct GenericArray
), TRUE
, TRUE
,
4119 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
4122 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4123 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4124 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4128 SetLastError(STATUS_ACCESS_VIOLATION
);
4135 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(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_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
4145 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
4146 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
4147 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
4148 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
4151 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4152 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
4153 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
4157 SetLastError(STATUS_ACCESS_VIOLATION
);
4164 #define RSA1_MAGIC 0x31415352
4166 struct DECODED_RSA_PUB_KEY
4169 CRYPT_INTEGER_BLOB modulus
;
4172 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
4173 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4174 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4180 struct AsnDecodeSequenceItem items
[] = {
4181 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
4182 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
4183 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
4185 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
4186 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4188 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
4191 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
4192 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
4193 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
4196 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
4197 decodedKey
->modulus
.cbData
;
4201 *pcbStructInfo
= bytesNeeded
;
4204 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4205 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4208 RSAPUBKEY
*rsaPubKey
;
4210 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4211 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4212 hdr
= (BLOBHEADER
*)pvStructInfo
;
4213 hdr
->bType
= PUBLICKEYBLOB
;
4214 hdr
->bVersion
= CUR_BLOB_VERSION
;
4216 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
4217 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
4218 sizeof(BLOBHEADER
));
4219 rsaPubKey
->magic
= RSA1_MAGIC
;
4220 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
4221 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
4222 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
4223 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
4224 decodedKey
->modulus
.cbData
);
4226 LocalFree(decodedKey
);
4231 SetLastError(STATUS_ACCESS_VIOLATION
);
4238 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
4239 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4240 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4243 DWORD bytesNeeded
, dataLen
;
4245 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4246 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4248 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4250 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4251 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
4253 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
4255 *pcbStructInfo
= bytesNeeded
;
4256 else if (*pcbStructInfo
< bytesNeeded
)
4258 SetLastError(ERROR_MORE_DATA
);
4259 *pcbStructInfo
= bytesNeeded
;
4264 CRYPT_DATA_BLOB
*blob
;
4265 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4267 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4268 blob
->cbData
= dataLen
;
4269 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4270 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
4273 assert(blob
->pbData
);
4275 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
4283 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
4284 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4285 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4289 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
4290 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4298 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4301 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
4303 SetLastError(CRYPT_E_ASN1_BADTAG
);
4306 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4307 lpszStructType
, pbEncoded
, cbEncoded
,
4308 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4311 *pcbStructInfo
= bytesNeeded
;
4312 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4313 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4315 CRYPT_DATA_BLOB
*blob
;
4317 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4318 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4319 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
4320 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
4321 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
4322 lpszStructType
, pbEncoded
, cbEncoded
,
4323 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4330 SetLastError(STATUS_ACCESS_VIOLATION
);
4337 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
4338 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4339 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4343 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
4344 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4346 if (pbEncoded
[0] == ASN_BITSTRING
)
4348 DWORD bytesNeeded
, dataLen
;
4350 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4352 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4353 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
4355 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
4357 *pcbStructInfo
= bytesNeeded
;
4358 else if (*pcbStructInfo
< bytesNeeded
)
4360 *pcbStructInfo
= bytesNeeded
;
4361 SetLastError(ERROR_MORE_DATA
);
4366 CRYPT_BIT_BLOB
*blob
;
4368 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4369 blob
->cbData
= dataLen
- 1;
4370 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
4371 GET_LEN_BYTES(pbEncoded
[1]));
4372 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
4374 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
4375 GET_LEN_BYTES(pbEncoded
[1]);
4379 assert(blob
->pbData
);
4382 BYTE mask
= 0xff << blob
->cUnusedBits
;
4384 memcpy(blob
->pbData
, pbEncoded
+ 2 +
4385 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
4386 blob
->pbData
[blob
->cbData
- 1] &= mask
;
4394 SetLastError(CRYPT_E_ASN1_BADTAG
);
4397 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4401 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
4402 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4403 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4407 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
4408 pDecodePara
, pvStructInfo
, pcbStructInfo
);
4414 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4415 lpszStructType
, pbEncoded
, cbEncoded
,
4416 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4419 *pcbStructInfo
= bytesNeeded
;
4420 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4421 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4423 CRYPT_BIT_BLOB
*blob
;
4425 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4426 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4427 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
4428 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
4429 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
4430 lpszStructType
, pbEncoded
, cbEncoded
,
4431 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4438 SetLastError(STATUS_ACCESS_VIOLATION
);
4442 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
4446 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
4447 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4448 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4454 *pcbStructInfo
= sizeof(int);
4459 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
4460 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
4461 DWORD size
= sizeof(buf
);
4463 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
4464 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4465 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
, &size
);
4468 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4469 pvStructInfo
, pcbStructInfo
, sizeof(int))))
4473 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4474 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4475 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
4477 /* initialize to a negative value to sign-extend */
4482 for (i
= 0; i
< blob
->cbData
; i
++)
4485 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
4487 memcpy(pvStructInfo
, &val
, sizeof(int));
4490 else if (GetLastError() == ERROR_MORE_DATA
)
4491 SetLastError(CRYPT_E_ASN1_LARGE
);
4495 SetLastError(STATUS_ACCESS_VIOLATION
);
4502 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
4503 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4504 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4508 if (pbEncoded
[0] == ASN_INTEGER
)
4510 DWORD bytesNeeded
, dataLen
;
4512 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4514 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4516 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4518 *pcbStructInfo
= bytesNeeded
;
4519 else if (*pcbStructInfo
< bytesNeeded
)
4521 *pcbStructInfo
= bytesNeeded
;
4522 SetLastError(ERROR_MORE_DATA
);
4527 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4529 blob
->cbData
= dataLen
;
4530 assert(blob
->pbData
);
4535 for (i
= 0; i
< blob
->cbData
; i
++)
4537 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4546 SetLastError(CRYPT_E_ASN1_BADTAG
);
4552 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
4553 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4554 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4562 if ((ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4563 lpszStructType
, pbEncoded
, cbEncoded
,
4564 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4567 *pcbStructInfo
= bytesNeeded
;
4568 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4569 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4571 CRYPT_INTEGER_BLOB
*blob
;
4573 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4574 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4575 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4576 blob
->pbData
= (BYTE
*)pvStructInfo
+
4577 sizeof(CRYPT_INTEGER_BLOB
);
4578 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
4579 lpszStructType
, pbEncoded
, cbEncoded
,
4580 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4587 SetLastError(STATUS_ACCESS_VIOLATION
);
4594 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
4595 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
4596 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4597 void *pvStructInfo
, DWORD
*pcbStructInfo
)
4601 if (pbEncoded
[0] == ASN_INTEGER
)
4603 DWORD bytesNeeded
, dataLen
;
4605 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
4607 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
4609 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
4611 *pcbStructInfo
= bytesNeeded
;
4612 else if (*pcbStructInfo
< bytesNeeded
)
4614 *pcbStructInfo
= bytesNeeded
;
4615 SetLastError(ERROR_MORE_DATA
);
4620 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4622 blob
->cbData
= dataLen
;
4623 assert(blob
->pbData
);
4624 /* remove leading zero byte if it exists */
4625 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
4634 for (i
= 0; i
< blob
->cbData
; i
++)
4636 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
4645 SetLastError(CRYPT_E_ASN1_BADTAG
);
4651 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
4652 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4653 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4661 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4662 lpszStructType
, pbEncoded
, cbEncoded
,
4663 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
4666 *pcbStructInfo
= bytesNeeded
;
4667 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4668 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
4670 CRYPT_INTEGER_BLOB
*blob
;
4672 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4673 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4674 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
4675 blob
->pbData
= (BYTE
*)pvStructInfo
+
4676 sizeof(CRYPT_INTEGER_BLOB
);
4677 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
4678 lpszStructType
, pbEncoded
, cbEncoded
,
4679 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
4686 SetLastError(STATUS_ACCESS_VIOLATION
);
4693 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
4694 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4695 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4701 *pcbStructInfo
= sizeof(int);
4706 if (pbEncoded
[0] == ASN_ENUMERATED
)
4708 unsigned int val
= 0, i
;
4712 SetLastError(CRYPT_E_ASN1_EOD
);
4715 else if (pbEncoded
[1] == 0)
4717 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4722 /* A little strange looking, but we have to accept a sign byte:
4723 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4724 * assuming a small length is okay here, it has to be in short
4727 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
4729 SetLastError(CRYPT_E_ASN1_LARGE
);
4732 for (i
= 0; i
< pbEncoded
[1]; i
++)
4735 val
|= pbEncoded
[2 + i
];
4737 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4738 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
4740 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4741 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4742 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
4748 SetLastError(CRYPT_E_ASN1_BADTAG
);
4754 SetLastError(STATUS_ACCESS_VIOLATION
);
4761 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4764 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4769 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4771 if (!isdigit(*(pbEncoded))) \
4773 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4779 (word) += *(pbEncoded)++ - '0'; \
4784 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
4785 SYSTEMTIME
*sysTime
)
4792 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
4794 WORD hours
, minutes
= 0;
4795 BYTE sign
= *pbEncoded
++;
4798 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
4799 if (ret
&& hours
>= 24)
4801 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4806 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
4807 if (ret
&& minutes
>= 60)
4809 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4817 sysTime
->wHour
+= hours
;
4818 sysTime
->wMinute
+= minutes
;
4822 if (hours
> sysTime
->wHour
)
4825 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
4828 sysTime
->wHour
-= hours
;
4829 if (minutes
> sysTime
->wMinute
)
4832 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
4835 sysTime
->wMinute
-= minutes
;
4842 SetLastError(STATUS_ACCESS_VIOLATION
);
4849 #define MIN_ENCODED_TIME_LENGTH 10
4851 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
4852 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4853 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4859 *pcbStructInfo
= sizeof(FILETIME
);
4865 if (pbEncoded
[0] == ASN_UTCTIME
)
4869 SetLastError(CRYPT_E_ASN1_EOD
);
4872 else if (pbEncoded
[1] > 0x7f)
4874 /* long-form date strings really can't be valid */
4875 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4880 SYSTEMTIME sysTime
= { 0 };
4881 BYTE len
= pbEncoded
[1];
4883 if (len
< MIN_ENCODED_TIME_LENGTH
)
4885 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4891 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
4892 if (sysTime
.wYear
>= 50)
4893 sysTime
.wYear
+= 1900;
4895 sysTime
.wYear
+= 2000;
4896 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
4897 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
4898 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
4899 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
4902 if (len
>= 2 && isdigit(*pbEncoded
) &&
4903 isdigit(*(pbEncoded
+ 1)))
4904 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4906 else if (isdigit(*pbEncoded
))
4907 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
4910 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
4913 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
4914 pDecodePara
, pvStructInfo
, pcbStructInfo
,
4917 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4918 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4919 ret
= SystemTimeToFileTime(&sysTime
,
4920 (FILETIME
*)pvStructInfo
);
4927 SetLastError(CRYPT_E_ASN1_BADTAG
);
4933 SetLastError(STATUS_ACCESS_VIOLATION
);
4940 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
4941 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4942 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4948 *pcbStructInfo
= sizeof(FILETIME
);
4954 if (pbEncoded
[0] == ASN_GENERALTIME
)
4958 SetLastError(CRYPT_E_ASN1_EOD
);
4961 else if (pbEncoded
[1] > 0x7f)
4963 /* long-form date strings really can't be valid */
4964 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4969 BYTE len
= pbEncoded
[1];
4971 if (len
< MIN_ENCODED_TIME_LENGTH
)
4973 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4978 SYSTEMTIME sysTime
= { 0 };
4981 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
4982 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
4983 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
4984 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
4987 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4990 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
4992 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
4999 /* workaround macro weirdness */
5000 digits
= min(len
, 3);
5001 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
5002 sysTime
.wMilliseconds
);
5005 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
5008 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
5009 pDecodePara
, pvStructInfo
, pcbStructInfo
,
5012 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5013 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5014 ret
= SystemTimeToFileTime(&sysTime
,
5015 (FILETIME
*)pvStructInfo
);
5022 SetLastError(CRYPT_E_ASN1_BADTAG
);
5028 SetLastError(STATUS_ACCESS_VIOLATION
);
5035 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
5036 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5037 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5043 if (pbEncoded
[0] == ASN_UTCTIME
)
5044 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
5045 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
5047 else if (pbEncoded
[0] == ASN_GENERALTIME
)
5048 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
5049 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
5050 pvStructInfo
, pcbStructInfo
);
5053 SetLastError(CRYPT_E_ASN1_BADTAG
);
5059 SetLastError(STATUS_ACCESS_VIOLATION
);
5066 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
5067 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5068 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5074 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
5076 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
5078 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
5083 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
5084 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
5086 ptr
= pbEncoded
+ 1 + lenBytes
;
5087 remainingLen
= dataLen
;
5088 while (ret
&& remainingLen
)
5092 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5095 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5097 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5098 ptr
+= 1 + nextLenBytes
+ nextLen
;
5099 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
5100 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
5101 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
5107 CRYPT_SEQUENCE_OF_ANY
*seq
;
5111 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
5112 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
5114 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
5115 pvStructInfo
= *(BYTE
**)pvStructInfo
;
5116 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
5117 seq
->cValue
= cValue
;
5118 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
5120 nextPtr
= (BYTE
*)seq
->rgValue
+
5121 cValue
* sizeof(CRYPT_DER_BLOB
);
5122 ptr
= pbEncoded
+ 1 + lenBytes
;
5123 remainingLen
= dataLen
;
5125 while (ret
&& remainingLen
)
5129 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
5132 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
5134 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
5136 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
5137 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
5140 seq
->rgValue
[i
].pbData
= nextPtr
;
5141 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
5143 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
5145 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
5146 ptr
+= 1 + nextLenBytes
+ nextLen
;
5156 SetLastError(CRYPT_E_ASN1_BADTAG
);
5162 SetLastError(STATUS_ACCESS_VIOLATION
);
5169 static BOOL WINAPI
CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType
,
5170 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5171 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5173 struct AsnDecodeSequenceItem items
[] = {
5174 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
5175 DistPointName
), CRYPT_AsnDecodeAltNameInternal
,
5176 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
5177 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
5178 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
5179 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
5180 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
5181 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
5182 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
5183 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
5187 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
5188 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
5189 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
5193 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
5194 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5195 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5199 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
5200 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
5204 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
5205 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
5206 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
5208 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
5209 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
5213 SetLastError(STATUS_ACCESS_VIOLATION
);
5220 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
5221 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5222 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5226 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
5227 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
5231 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
5232 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), TRUE
, 0 };
5234 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
5235 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
5239 SetLastError(STATUS_ACCESS_VIOLATION
);
5246 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
5247 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
5248 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
5250 static HCRYPTOIDFUNCSET set
= NULL
;
5252 CryptDecodeObjectExFunc decodeFunc
= NULL
;
5253 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5255 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
5256 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
5257 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5259 if (!pvStructInfo
&& !pcbStructInfo
)
5261 SetLastError(ERROR_INVALID_PARAMETER
);
5264 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
5265 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
5267 SetLastError(ERROR_FILE_NOT_FOUND
);
5272 SetLastError(CRYPT_E_ASN1_EOD
);
5275 if (cbEncoded
> MAX_ENCODED_LEN
)
5277 SetLastError(CRYPT_E_ASN1_LARGE
);
5281 SetLastError(NOERROR
);
5282 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
5283 *(BYTE
**)pvStructInfo
= NULL
;
5284 if (!HIWORD(lpszStructType
))
5286 switch (LOWORD(lpszStructType
))
5288 case (WORD
)X509_CERT
:
5289 decodeFunc
= CRYPT_AsnDecodeCert
;
5291 case (WORD
)X509_CERT_TO_BE_SIGNED
:
5292 decodeFunc
= CRYPT_AsnDecodeCertInfo
;
5294 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
5295 decodeFunc
= CRYPT_AsnDecodeCRLInfo
;
5297 case (WORD
)X509_EXTENSIONS
:
5298 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5300 case (WORD
)X509_NAME
:
5301 decodeFunc
= CRYPT_AsnDecodeName
;
5303 case (WORD
)X509_PUBLIC_KEY_INFO
:
5304 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
5306 case (WORD
)X509_ALTERNATE_NAME
:
5307 decodeFunc
= CRYPT_AsnDecodeAltName
;
5309 case (WORD
)X509_BASIC_CONSTRAINTS
:
5310 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
5312 case (WORD
)X509_BASIC_CONSTRAINTS2
:
5313 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5315 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
5316 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
5318 case (WORD
)X509_OCTET_STRING
:
5319 decodeFunc
= CRYPT_AsnDecodeOctets
;
5321 case (WORD
)X509_BITS
:
5322 case (WORD
)X509_KEY_USAGE
:
5323 decodeFunc
= CRYPT_AsnDecodeBits
;
5325 case (WORD
)X509_INTEGER
:
5326 decodeFunc
= CRYPT_AsnDecodeInt
;
5328 case (WORD
)X509_MULTI_BYTE_INTEGER
:
5329 decodeFunc
= CRYPT_AsnDecodeInteger
;
5331 case (WORD
)X509_MULTI_BYTE_UINT
:
5332 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
5334 case (WORD
)X509_ENUMERATED
:
5335 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5337 case (WORD
)X509_CHOICE_OF_TIME
:
5338 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
5340 case (WORD
)X509_SEQUENCE_OF_ANY
:
5341 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
5343 case (WORD
)PKCS_UTC_TIME
:
5344 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5346 case (WORD
)X509_CRL_DIST_POINTS
:
5347 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
5349 case (WORD
)X509_ENHANCED_KEY_USAGE
:
5350 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
5353 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
5356 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
5357 decodeFunc
= CRYPT_AsnDecodeExtensions
;
5358 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
5359 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
5360 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
5361 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
5362 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
5363 decodeFunc
= CRYPT_AsnDecodeBits
;
5364 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
5365 decodeFunc
= CRYPT_AsnDecodeOctets
;
5366 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
5367 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
5368 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
5369 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
5370 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
5371 decodeFunc
= CRYPT_AsnDecodeAltName
;
5372 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
5373 decodeFunc
= CRYPT_AsnDecodeAltName
;
5374 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
5375 decodeFunc
= CRYPT_AsnDecodeAltName
;
5376 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
5377 decodeFunc
= CRYPT_AsnDecodeAltName
;
5378 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
5379 decodeFunc
= CRYPT_AsnDecodeAltName
;
5380 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
5381 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
5382 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
5383 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
5385 TRACE("OID %s not found or unimplemented, looking for DLL\n",
5386 debugstr_a(lpszStructType
));
5390 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
5391 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
5392 (void **)&decodeFunc
, &hFunc
);
5395 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
5396 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
5398 SetLastError(ERROR_FILE_NOT_FOUND
);
5400 CryptFreeOIDFunctionAddress(hFunc
, 0);
5404 BOOL WINAPI
CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5405 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5407 return CryptExportPublicKeyInfoEx(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5408 NULL
, 0, NULL
, pInfo
, pcbInfo
);
5411 static BOOL WINAPI
CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5412 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5413 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5418 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5419 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5422 if (!pszPublicKeyObjId
)
5423 pszPublicKeyObjId
= szOID_RSA_RSA
;
5424 if ((ret
= CryptGetUserKey(hCryptProv
, dwKeySpec
, &key
)))
5428 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, NULL
, &keySize
);
5431 LPBYTE pubKey
= CryptMemAlloc(keySize
);
5435 ret
= CryptExportKey(key
, 0, PUBLICKEYBLOB
, 0, pubKey
,
5439 DWORD encodedLen
= 0;
5441 ret
= CryptEncodeObject(dwCertEncodingType
,
5442 RSA_CSP_PUBLICKEYBLOB
, pubKey
, NULL
, &encodedLen
);
5445 DWORD sizeNeeded
= sizeof(CERT_PUBLIC_KEY_INFO
) +
5446 strlen(pszPublicKeyObjId
) + 1 + encodedLen
;
5449 *pcbInfo
= sizeNeeded
;
5450 else if (*pcbInfo
< sizeNeeded
)
5452 SetLastError(ERROR_MORE_DATA
);
5453 *pcbInfo
= sizeNeeded
;
5458 pInfo
->Algorithm
.pszObjId
= (char *)pInfo
+
5459 sizeof(CERT_PUBLIC_KEY_INFO
);
5460 lstrcpyA(pInfo
->Algorithm
.pszObjId
,
5462 pInfo
->Algorithm
.Parameters
.cbData
= 0;
5463 pInfo
->Algorithm
.Parameters
.pbData
= NULL
;
5464 pInfo
->PublicKey
.pbData
=
5465 (BYTE
*)pInfo
->Algorithm
.pszObjId
5466 + lstrlenA(pInfo
->Algorithm
.pszObjId
) + 1;
5467 pInfo
->PublicKey
.cbData
= encodedLen
;
5468 pInfo
->PublicKey
.cUnusedBits
= 0;
5469 ret
= CryptEncodeObject(dwCertEncodingType
,
5470 RSA_CSP_PUBLICKEYBLOB
, pubKey
,
5471 pInfo
->PublicKey
.pbData
, &pInfo
->PublicKey
.cbData
);
5475 CryptMemFree(pubKey
);
5480 CryptDestroyKey(key
);
5485 typedef BOOL (WINAPI
*ExportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5486 DWORD dwKeySpec
, DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
,
5487 DWORD dwFlags
, void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
);
5489 BOOL WINAPI
CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv
, DWORD dwKeySpec
,
5490 DWORD dwCertEncodingType
, LPSTR pszPublicKeyObjId
, DWORD dwFlags
,
5491 void *pvAuxInfo
, PCERT_PUBLIC_KEY_INFO pInfo
, DWORD
*pcbInfo
)
5493 static HCRYPTOIDFUNCSET set
= NULL
;
5495 ExportPublicKeyInfoExFunc exportFunc
= NULL
;
5496 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5498 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv
, dwKeySpec
,
5499 dwCertEncodingType
, debugstr_a(pszPublicKeyObjId
), dwFlags
, pvAuxInfo
,
5504 SetLastError(ERROR_INVALID_PARAMETER
);
5508 if (pszPublicKeyObjId
)
5511 set
= CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC
,
5513 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, pszPublicKeyObjId
,
5514 0, (void **)&exportFunc
, &hFunc
);
5517 exportFunc
= CRYPT_ExportRsaPublicKeyInfoEx
;
5518 ret
= exportFunc(hCryptProv
, dwKeySpec
, dwCertEncodingType
,
5519 pszPublicKeyObjId
, dwFlags
, pvAuxInfo
, pInfo
, pcbInfo
);
5521 CryptFreeOIDFunctionAddress(hFunc
, 0);
5525 BOOL WINAPI
CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv
,
5526 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, HCRYPTKEY
*phKey
)
5528 return CryptImportPublicKeyInfoEx(hCryptProv
, dwCertEncodingType
, pInfo
,
5532 static BOOL WINAPI
CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5533 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5534 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5537 DWORD pubKeySize
= 0;
5539 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5540 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5542 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5543 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, NULL
, &pubKeySize
);
5546 LPBYTE pubKey
= CryptMemAlloc(pubKeySize
);
5550 ret
= CryptDecodeObject(dwCertEncodingType
, RSA_CSP_PUBLICKEYBLOB
,
5551 pInfo
->PublicKey
.pbData
, pInfo
->PublicKey
.cbData
, 0, pubKey
,
5554 ret
= CryptImportKey(hCryptProv
, pubKey
, pubKeySize
, 0, 0,
5556 CryptMemFree(pubKey
);
5564 typedef BOOL (WINAPI
*ImportPublicKeyInfoExFunc
)(HCRYPTPROV hCryptProv
,
5565 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5566 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
);
5568 BOOL WINAPI
CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv
,
5569 DWORD dwCertEncodingType
, PCERT_PUBLIC_KEY_INFO pInfo
, ALG_ID aiKeyAlg
,
5570 DWORD dwFlags
, void *pvAuxInfo
, HCRYPTKEY
*phKey
)
5572 static HCRYPTOIDFUNCSET set
= NULL
;
5574 ImportPublicKeyInfoExFunc importFunc
= NULL
;
5575 HCRYPTOIDFUNCADDR hFunc
= NULL
;
5577 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv
,
5578 dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
, pvAuxInfo
, phKey
);
5581 set
= CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC
, 0);
5582 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
,
5583 pInfo
->Algorithm
.pszObjId
, 0, (void **)&importFunc
, &hFunc
);
5585 importFunc
= CRYPT_ImportRsaPublicKeyInfoEx
;
5586 ret
= importFunc(hCryptProv
, dwCertEncodingType
, pInfo
, aiKeyAlg
, dwFlags
,
5589 CryptFreeOIDFunctionAddress(hFunc
, 0);