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