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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * 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
39 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "wine/unicode.h"
48 #include "crypt32_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
98 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
100 static HCRYPTOIDFUNCSET set = NULL;
102 HCRYPTOIDFUNCADDR hFunc;
103 CryptEncodeObjectFunc pCryptEncodeObject;
105 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
106 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
109 if (!pbEncoded && !pcbEncoded)
111 SetLastError(ERROR_INVALID_PARAMETER);
115 /* Try registered DLL first.. */
117 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
118 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
119 (void **)&pCryptEncodeObject, &hFunc);
120 if (pCryptEncodeObject)
122 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
123 pvStructInfo, pbEncoded, pcbEncoded);
124 CryptFreeOIDFunctionAddress(hFunc, 0);
128 /* If not, use CryptEncodeObjectEx */
129 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
130 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
135 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
136 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
140 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
142 if (pEncodePara && pEncodePara->pfnAlloc)
143 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
145 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
146 if (!*(BYTE **)pbEncoded)
149 *pcbEncoded = bytesNeeded;
151 else if (bytesNeeded > *pcbEncoded)
153 *pcbEncoded = bytesNeeded;
154 SetLastError(ERROR_MORE_DATA);
158 *pcbEncoded = bytesNeeded;
162 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
164 DWORD bytesNeeded, significantBytes = 0;
172 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
173 temp <<= 8, significantBytes--)
175 bytesNeeded = significantBytes + 1;
179 *pcbEncoded = bytesNeeded;
182 if (*pcbEncoded < bytesNeeded)
184 SetLastError(ERROR_MORE_DATA);
188 *pbEncoded = (BYTE)len;
193 *pbEncoded++ = significantBytes | 0x80;
194 for (i = 0; i < significantBytes; i++)
196 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
200 *pcbEncoded = bytesNeeded;
204 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
205 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
206 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
209 DWORD i, dataLen = 0;
211 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
212 pbEncoded, *pcbEncoded);
213 for (i = 0, ret = TRUE; ret && i < cItem; i++)
215 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
216 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
217 NULL, &items[i].size);
218 /* Some functions propagate their errors through the size */
220 *pcbEncoded = items[i].size;
221 dataLen += items[i].size;
225 DWORD lenBytes, bytesNeeded;
227 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
228 bytesNeeded = 1 + lenBytes + dataLen;
230 *pcbEncoded = bytesNeeded;
233 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
234 pcbEncoded, bytesNeeded)))
236 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
237 pbEncoded = *(BYTE **)pbEncoded;
238 *pbEncoded++ = ASN_SEQUENCE;
239 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
240 pbEncoded += lenBytes;
241 for (i = 0; ret && i < cItem; i++)
243 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
244 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
245 NULL, pbEncoded, &items[i].size);
246 /* Some functions propagate their errors through the size */
248 *pcbEncoded = items[i].size;
249 pbEncoded += items[i].size;
254 TRACE("returning %d (%08x)\n", ret, GetLastError());
258 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
259 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
260 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
263 const struct AsnConstructedItem *item =
264 (const struct AsnConstructedItem *)pvStructInfo;
267 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
268 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
270 DWORD dataLen, bytesNeeded;
272 CRYPT_EncodeLen(len, NULL, &dataLen);
273 bytesNeeded = 1 + dataLen + len;
275 *pcbEncoded = bytesNeeded;
276 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
277 pbEncoded, pcbEncoded, bytesNeeded)))
279 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
280 pbEncoded = *(BYTE **)pbEncoded;
281 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
282 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
283 pbEncoded += dataLen;
284 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
285 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
289 /* Some functions propagate their errors through the size */
296 /* Some functions propagate their errors through the size */
302 struct AsnEncodeTagSwappedItem
305 const void *pvStructInfo;
306 CryptEncodeObjectExFunc encodeFunc;
309 /* Sort of a wacky hack, it encodes something using the struct
310 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
311 * given in the struct AsnEncodeTagSwappedItem.
313 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
314 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
315 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
318 const struct AsnEncodeTagSwappedItem *item =
319 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
321 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
322 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
323 if (ret && pbEncoded)
324 *pbEncoded = item->tag;
328 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
329 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
330 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
332 const DWORD *ver = (const DWORD *)pvStructInfo;
335 /* CERT_V1 is not encoded */
343 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
345 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
346 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
351 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
352 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
353 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
355 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
360 *pcbEncoded = blob->cbData;
365 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
366 pcbEncoded, blob->cbData)))
368 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
369 pbEncoded = *(BYTE **)pbEncoded;
371 memcpy(pbEncoded, blob->pbData, blob->cbData);
372 *pcbEncoded = blob->cbData;
379 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
380 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
381 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
384 /* This has two filetimes in a row, a NotBefore and a NotAfter */
385 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
386 struct AsnEncodeSequenceItem items[] = {
387 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
388 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
391 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
392 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
397 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
398 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
399 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
402 const CRYPT_ALGORITHM_IDENTIFIER *algo =
403 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
405 struct AsnEncodeSequenceItem items[] = {
406 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
407 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
410 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
411 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
416 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
417 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
418 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
424 const CERT_PUBLIC_KEY_INFO *info =
425 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
426 struct AsnEncodeSequenceItem items[] = {
427 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
428 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
431 TRACE("Encoding public key with OID %s\n",
432 debugstr_a(info->Algorithm.pszObjId));
433 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
434 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
439 SetLastError(STATUS_ACCESS_VIOLATION);
446 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
447 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
448 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
454 const CERT_SIGNED_CONTENT_INFO *info =
455 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
456 struct AsnEncodeSequenceItem items[] = {
457 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
458 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
459 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
462 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
463 items[2].encodeFunc = CRYPT_AsnEncodeBits;
464 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
465 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
470 SetLastError(STATUS_ACCESS_VIOLATION);
477 /* Like in Windows, this blithely ignores the validity of the passed-in
478 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
479 * decode properly, see CRYPT_AsnDecodeCertInfo.
481 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
482 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
483 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
489 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
490 struct AsnEncodeSequenceItem items[10] = {
491 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
492 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
493 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
494 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
495 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
496 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
497 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
500 struct AsnConstructedItem constructed[3] = { { 0 } };
501 DWORD cItem = 7, cConstructed = 0;
503 if (info->IssuerUniqueId.cbData)
505 constructed[cConstructed].tag = 1;
506 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
507 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
508 items[cItem].pvStructInfo = &constructed[cConstructed];
509 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
513 if (info->SubjectUniqueId.cbData)
515 constructed[cConstructed].tag = 2;
516 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
517 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
518 items[cItem].pvStructInfo = &constructed[cConstructed];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
523 if (info->cExtension)
525 constructed[cConstructed].tag = 3;
526 constructed[cConstructed].pvStructInfo = &info->cExtension;
527 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
528 items[cItem].pvStructInfo = &constructed[cConstructed];
529 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
534 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
535 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
539 SetLastError(STATUS_ACCESS_VIOLATION);
546 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
547 BYTE *pbEncoded, DWORD *pcbEncoded)
549 struct AsnEncodeSequenceItem items[3] = {
550 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
551 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
557 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
559 if (entry->cExtension)
561 items[cItem].pvStructInfo = &entry->cExtension;
562 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
566 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
567 pbEncoded, pcbEncoded);
569 TRACE("returning %d (%08x)\n", ret, GetLastError());
573 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
574 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
575 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
577 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
578 DWORD bytesNeeded, dataLen, lenBytes, i;
579 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
580 ((const BYTE *)pvStructInfo + sizeof(DWORD));
583 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
587 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
591 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
592 bytesNeeded = 1 + lenBytes + dataLen;
594 *pcbEncoded = bytesNeeded;
597 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
598 pcbEncoded, bytesNeeded)))
600 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
601 pbEncoded = *(BYTE **)pbEncoded;
602 *pbEncoded++ = ASN_SEQUENCEOF;
603 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
604 pbEncoded += lenBytes;
605 for (i = 0; i < cCRLEntry; i++)
607 DWORD size = dataLen;
609 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
618 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
619 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
620 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
622 const DWORD *ver = (const DWORD *)pvStructInfo;
625 /* CRL_V1 is not encoded */
632 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
633 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
637 /* Like in Windows, this blithely ignores the validity of the passed-in
638 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
639 * decode properly, see CRYPT_AsnDecodeCRLInfo.
641 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
642 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
643 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
649 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
650 struct AsnEncodeSequenceItem items[7] = {
651 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
652 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
653 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
654 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
657 struct AsnConstructedItem constructed[1] = { { 0 } };
658 DWORD cItem = 4, cConstructed = 0;
660 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
662 items[cItem].pvStructInfo = &info->NextUpdate;
663 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
668 items[cItem].pvStructInfo = &info->cCRLEntry;
669 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
672 if (info->cExtension)
674 constructed[cConstructed].tag = 0;
675 constructed[cConstructed].pvStructInfo = &info->cExtension;
676 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
677 items[cItem].pvStructInfo = &constructed[cConstructed];
678 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
683 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
684 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
688 SetLastError(STATUS_ACCESS_VIOLATION);
695 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
699 struct AsnEncodeSequenceItem items[3] = {
700 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
706 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
710 items[cItem].pvStructInfo = &ext->fCritical;
711 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
714 items[cItem].pvStructInfo = &ext->Value;
715 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
718 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
719 pbEncoded, pcbEncoded);
720 TRACE("returning %d (%08x)\n", ret, GetLastError());
724 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
725 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
726 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
732 DWORD bytesNeeded, dataLen, lenBytes, i;
733 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
736 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
740 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
744 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
745 bytesNeeded = 1 + lenBytes + dataLen;
747 *pcbEncoded = bytesNeeded;
750 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
751 pcbEncoded, bytesNeeded)))
753 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
754 pbEncoded = *(BYTE **)pbEncoded;
755 *pbEncoded++ = ASN_SEQUENCEOF;
756 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
757 pbEncoded += lenBytes;
758 for (i = 0; i < exts->cExtension; i++)
760 DWORD size = dataLen;
762 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
772 SetLastError(STATUS_ACCESS_VIOLATION);
779 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
780 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
781 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
783 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
784 DWORD bytesNeeded = 0, lenBytes;
789 TRACE("%s\n", debugstr_a(pszObjId));
796 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
798 SetLastError(CRYPT_E_ASN1_ERROR);
802 firstByte = val1 * 40 + val2;
803 ptr = pszObjId + firstPos;
808 /* note I assume each component is at most 32-bits long in base 2 */
809 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
811 if (val1 >= 0x10000000)
813 else if (val1 >= 0x200000)
815 else if (val1 >= 0x4000)
817 else if (val1 >= 0x80)
827 SetLastError(CRYPT_E_ASN1_ERROR);
831 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
835 bytesNeeded += 1 + lenBytes;
838 if (*pcbEncoded < bytesNeeded)
840 SetLastError(ERROR_MORE_DATA);
845 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
846 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
847 pbEncoded += lenBytes;
853 *pbEncoded++ = firstByte;
854 ptr = pszObjId + firstPos;
857 sscanf(ptr, "%d%n", &val, &pos);
859 unsigned char outBytes[5];
862 if (val >= 0x10000000)
864 else if (val >= 0x200000)
866 else if (val >= 0x4000)
868 else if (val >= 0x80)
872 for (i = numBytes; i > 0; i--)
874 outBytes[i - 1] = val & 0x7f;
877 for (i = 0; i < numBytes - 1; i++)
878 *pbEncoded++ = outBytes[i] | 0x80;
879 *pbEncoded++ = outBytes[i];
888 *pcbEncoded = bytesNeeded;
892 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
893 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
897 LPCSTR str = (LPCSTR)value->Value.pbData;
898 DWORD bytesNeeded, lenBytes, encodedLen;
900 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
901 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
902 bytesNeeded = 1 + lenBytes + encodedLen;
904 *pcbEncoded = bytesNeeded;
907 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
908 pbEncoded, pcbEncoded, bytesNeeded)))
910 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
911 pbEncoded = *(BYTE **)pbEncoded;
913 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
914 pbEncoded += lenBytes;
915 memcpy(pbEncoded, str, encodedLen);
921 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
922 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
926 LPCWSTR str = (LPCWSTR)value->Value.pbData;
927 DWORD bytesNeeded, lenBytes, strLen;
929 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
931 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
932 bytesNeeded = 1 + lenBytes + strLen * 2;
934 *pcbEncoded = bytesNeeded;
937 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
938 pbEncoded, pcbEncoded, bytesNeeded)))
942 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
943 pbEncoded = *(BYTE **)pbEncoded;
944 *pbEncoded++ = ASN_BMPSTRING;
945 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
946 pbEncoded += lenBytes;
947 for (i = 0; i < strLen; i++)
949 *pbEncoded++ = (str[i] & 0xff00) >> 8;
950 *pbEncoded++ = str[i] & 0x00ff;
957 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
958 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
962 LPCWSTR str = (LPCWSTR)value->Value.pbData;
963 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
965 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
967 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
969 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
970 bytesNeeded = 1 + lenBytes + encodedLen;
972 *pcbEncoded = bytesNeeded;
975 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
976 pbEncoded, pcbEncoded, bytesNeeded)))
978 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
979 pbEncoded = *(BYTE **)pbEncoded;
980 *pbEncoded++ = ASN_UTF8STRING;
981 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
982 pbEncoded += lenBytes;
983 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
984 bytesNeeded - lenBytes - 1, NULL, NULL);
990 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
991 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
992 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
998 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1000 switch (value->dwValueType)
1002 case CERT_RDN_ANY_TYPE:
1003 /* explicitly disallowed */
1004 SetLastError(E_INVALIDARG);
1007 case CERT_RDN_ENCODED_BLOB:
1008 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1009 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1011 case CERT_RDN_OCTET_STRING:
1012 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1013 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1015 case CERT_RDN_NUMERIC_STRING:
1016 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1017 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1019 case CERT_RDN_PRINTABLE_STRING:
1020 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1021 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1023 case CERT_RDN_TELETEX_STRING:
1024 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1025 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1027 case CERT_RDN_VIDEOTEX_STRING:
1028 ret = CRYPT_AsnEncodeStringCoerce(value,
1029 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1031 case CERT_RDN_IA5_STRING:
1032 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1033 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1035 case CERT_RDN_GRAPHIC_STRING:
1036 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1037 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1039 case CERT_RDN_VISIBLE_STRING:
1040 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1041 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1043 case CERT_RDN_GENERAL_STRING:
1044 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1045 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1047 case CERT_RDN_UNIVERSAL_STRING:
1048 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1049 SetLastError(CRYPT_E_ASN1_CHOICE);
1052 case CERT_RDN_BMP_STRING:
1053 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1054 pbEncoded, pcbEncoded);
1056 case CERT_RDN_UTF8_STRING:
1057 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1058 pbEncoded, pcbEncoded);
1061 SetLastError(CRYPT_E_ASN1_CHOICE);
1067 SetLastError(STATUS_ACCESS_VIOLATION);
1074 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1075 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1076 BYTE *pbEncoded, DWORD *pcbEncoded)
1078 DWORD bytesNeeded = 0, lenBytes, size;
1081 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1082 0, NULL, NULL, &size);
1085 bytesNeeded += size;
1086 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1087 * with dwValueType, so "cast" it to get its encoded size
1089 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1090 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1093 bytesNeeded += size;
1094 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1095 bytesNeeded += 1 + lenBytes;
1098 if (*pcbEncoded < bytesNeeded)
1100 SetLastError(ERROR_MORE_DATA);
1105 *pbEncoded++ = ASN_SEQUENCE;
1106 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1108 pbEncoded += lenBytes;
1109 size = bytesNeeded - 1 - lenBytes;
1110 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1111 attr->pszObjId, 0, NULL, pbEncoded, &size);
1115 size = bytesNeeded - 1 - lenBytes - size;
1116 ret = nameValueEncodeFunc(dwCertEncodingType,
1117 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1118 0, NULL, pbEncoded, &size);
1125 *pcbEncoded = bytesNeeded;
1129 /* Have to propagate index of failing character */
1136 static int BLOBComp(const void *l, const void *r)
1138 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1141 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1142 ret = a->cbData - b->cbData;
1146 typedef struct _CRYPT_SET_OF {
1148 PCRYPT_DER_BLOB rgValue;
1151 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1153 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1154 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1155 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1157 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1158 DWORD bytesNeeded = 0, lenBytes, i;
1161 for (i = 0; i < set->cValue; i++)
1162 bytesNeeded += set->rgValue[i].cbData;
1163 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1164 bytesNeeded += 1 + lenBytes;
1167 *pcbEncoded = bytesNeeded;
1170 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1171 pbEncoded, pcbEncoded, bytesNeeded)))
1173 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1174 pbEncoded = *(BYTE **)pbEncoded;
1175 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1176 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1177 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1178 pbEncoded += lenBytes;
1179 for (i = 0; ret && i < set->cValue; i++)
1181 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1182 pbEncoded += set->rgValue[i].cbData;
1188 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1189 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1193 CRYPT_SET_OF setOf = { 0, NULL };
1202 setOf.cValue = rdn->cRDNAttr;
1203 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1204 sizeof(CRYPT_DER_BLOB));
1208 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1210 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1212 setOf.rgValue[i].cbData = 0;
1213 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1214 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1217 setOf.rgValue[i].pbData =
1218 CryptMemAlloc(setOf.rgValue[i].cbData);
1219 if (!setOf.rgValue[i].pbData)
1222 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1223 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1224 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1228 /* Have to propagate index of failing character */
1229 *pcbEncoded = setOf.rgValue[i].cbData;
1233 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1234 pbEncoded, pcbEncoded);
1235 for (i = 0; i < setOf.cValue; i++)
1236 CryptMemFree(setOf.rgValue[i].pbData);
1240 SetLastError(STATUS_ACCESS_VIOLATION);
1244 CryptMemFree(setOf.rgValue);
1248 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1249 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1250 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1252 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1253 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1254 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1257 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1260 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1261 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1262 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1264 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1265 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1269 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1270 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1271 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1277 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1278 DWORD bytesNeeded = 0, lenBytes, size, i;
1280 TRACE("encoding name with %d RDNs\n", info->cRDN);
1282 for (i = 0; ret && i < info->cRDN; i++)
1284 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1285 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1287 bytesNeeded += size;
1291 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1292 bytesNeeded += 1 + lenBytes;
1296 *pcbEncoded = bytesNeeded;
1299 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1300 pbEncoded, pcbEncoded, bytesNeeded)))
1302 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1303 pbEncoded = *(BYTE **)pbEncoded;
1304 *pbEncoded++ = ASN_SEQUENCEOF;
1305 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1307 pbEncoded += lenBytes;
1308 for (i = 0; ret && i < info->cRDN; i++)
1311 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1312 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1317 bytesNeeded -= size;
1328 SetLastError(STATUS_ACCESS_VIOLATION);
1335 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1336 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1337 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1343 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1345 if (!attr->pszObjId)
1346 SetLastError(E_INVALIDARG);
1349 struct AsnEncodeSequenceItem items[2] = {
1350 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1351 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1354 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1355 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1361 SetLastError(STATUS_ACCESS_VIOLATION);
1367 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1368 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1369 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1372 CRYPT_SET_OF setOf = { 0, NULL };
1377 const CRYPT_ATTRIBUTES *attributes =
1378 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1381 if (attributes->cAttr)
1383 setOf.cValue = attributes->cAttr;
1384 setOf.rgValue = CryptMemAlloc(attributes->cAttr *
1385 sizeof(CRYPT_DER_BLOB));
1389 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1391 for (i = 0; ret && i < attributes->cAttr; i++)
1393 ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
1394 &attributes->rgAttr[i], 0, NULL, NULL, &setOf.rgValue[i].cbData);
1397 setOf.rgValue[i].pbData =
1398 CryptMemAlloc(setOf.rgValue[i].cbData);
1399 if (!setOf.rgValue[i].pbData)
1403 ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
1404 &attributes->rgAttr[i], 0, NULL, setOf.rgValue[i].pbData,
1405 &setOf.rgValue[i].cbData);
1410 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, dwFlags,
1411 pEncodePara, pbEncoded, pcbEncoded);
1412 for (i = 0; i < setOf.cValue; i++)
1413 CryptMemFree(setOf.rgValue[i].pbData);
1417 SetLastError(STATUS_ACCESS_VIOLATION);
1420 CryptMemFree(setOf.rgValue);
1424 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1425 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1426 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1432 const CRYPT_CONTENT_INFO *info =
1433 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1435 if (!info->pszObjId)
1436 SetLastError(E_INVALIDARG);
1439 struct AsnEncodeSequenceItem items[2] = {
1440 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1443 struct AsnConstructedItem constructed = { 0 };
1446 if (info->Content.cbData)
1448 constructed.tag = 0;
1449 constructed.pvStructInfo = &info->Content;
1450 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1451 items[cItem].pvStructInfo = &constructed;
1452 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1455 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1456 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1462 SetLastError(STATUS_ACCESS_VIOLATION);
1468 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1469 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1473 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1474 DWORD bytesNeeded, lenBytes, encodedLen;
1476 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1478 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1479 bytesNeeded = 1 + lenBytes + encodedLen;
1481 *pcbEncoded = bytesNeeded;
1484 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1485 pbEncoded, pcbEncoded, bytesNeeded)))
1489 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1490 pbEncoded = *(BYTE **)pbEncoded;
1492 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1493 pbEncoded += lenBytes;
1494 for (i = 0; i < encodedLen; i++)
1495 *pbEncoded++ = (BYTE)str[i];
1501 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1502 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1506 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1507 DWORD bytesNeeded, lenBytes, encodedLen;
1509 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1511 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1512 bytesNeeded = 1 + lenBytes + encodedLen;
1514 *pcbEncoded = bytesNeeded;
1517 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1518 pbEncoded, pcbEncoded, bytesNeeded)))
1522 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1523 pbEncoded = *(BYTE **)pbEncoded;
1524 *pbEncoded++ = ASN_NUMERICSTRING;
1525 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1526 pbEncoded += lenBytes;
1527 for (i = 0; ret && i < encodedLen; i++)
1529 if (isdigitW(str[i]))
1530 *pbEncoded++ = (BYTE)str[i];
1534 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1543 static inline int isprintableW(WCHAR wc)
1545 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1546 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1547 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1550 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1551 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1555 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1556 DWORD bytesNeeded, lenBytes, encodedLen;
1558 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1560 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1561 bytesNeeded = 1 + lenBytes + encodedLen;
1563 *pcbEncoded = bytesNeeded;
1566 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1567 pbEncoded, pcbEncoded, bytesNeeded)))
1571 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1572 pbEncoded = *(BYTE **)pbEncoded;
1573 *pbEncoded++ = ASN_PRINTABLESTRING;
1574 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1575 pbEncoded += lenBytes;
1576 for (i = 0; ret && i < encodedLen; i++)
1578 if (isprintableW(str[i]))
1579 *pbEncoded++ = (BYTE)str[i];
1583 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1592 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1593 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1597 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1598 DWORD bytesNeeded, lenBytes, encodedLen;
1600 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1602 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1603 bytesNeeded = 1 + lenBytes + encodedLen;
1605 *pcbEncoded = bytesNeeded;
1608 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1609 pbEncoded, pcbEncoded, bytesNeeded)))
1613 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1614 pbEncoded = *(BYTE **)pbEncoded;
1615 *pbEncoded++ = ASN_IA5STRING;
1616 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1617 pbEncoded += lenBytes;
1618 for (i = 0; ret && i < encodedLen; i++)
1621 *pbEncoded++ = (BYTE)str[i];
1625 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1634 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1635 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1639 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1640 DWORD bytesNeeded, lenBytes, strLen;
1642 /* FIXME: doesn't handle composite characters */
1643 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1645 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1646 bytesNeeded = 1 + lenBytes + strLen * 4;
1648 *pcbEncoded = bytesNeeded;
1651 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1652 pbEncoded, pcbEncoded, bytesNeeded)))
1656 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1657 pbEncoded = *(BYTE **)pbEncoded;
1658 *pbEncoded++ = ASN_UNIVERSALSTRING;
1659 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1660 pbEncoded += lenBytes;
1661 for (i = 0; i < strLen; i++)
1665 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1666 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1673 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1674 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1675 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1681 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1683 switch (value->dwValueType)
1685 case CERT_RDN_ANY_TYPE:
1686 case CERT_RDN_ENCODED_BLOB:
1687 case CERT_RDN_OCTET_STRING:
1688 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1690 case CERT_RDN_NUMERIC_STRING:
1691 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1692 pbEncoded, pcbEncoded);
1694 case CERT_RDN_PRINTABLE_STRING:
1695 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1696 pbEncoded, pcbEncoded);
1698 case CERT_RDN_TELETEX_STRING:
1699 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1700 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1702 case CERT_RDN_VIDEOTEX_STRING:
1703 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1704 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1706 case CERT_RDN_IA5_STRING:
1707 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1708 pbEncoded, pcbEncoded);
1710 case CERT_RDN_GRAPHIC_STRING:
1711 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1712 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1714 case CERT_RDN_VISIBLE_STRING:
1715 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1716 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1718 case CERT_RDN_GENERAL_STRING:
1719 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1720 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1722 case CERT_RDN_UNIVERSAL_STRING:
1723 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1724 pbEncoded, pcbEncoded);
1726 case CERT_RDN_BMP_STRING:
1727 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1728 pbEncoded, pcbEncoded);
1730 case CERT_RDN_UTF8_STRING:
1731 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1732 pbEncoded, pcbEncoded);
1735 SetLastError(CRYPT_E_ASN1_CHOICE);
1740 SetLastError(STATUS_ACCESS_VIOLATION);
1746 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1747 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1748 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1754 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1755 DWORD bytesNeeded = 0, lenBytes, size, i;
1757 TRACE("encoding name with %d RDNs\n", info->cRDN);
1759 for (i = 0; ret && i < info->cRDN; i++)
1761 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1762 CRYPT_AsnEncodeNameValue, NULL, &size);
1764 bytesNeeded += size;
1766 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1767 bytesNeeded += 1 + lenBytes;
1771 *pcbEncoded = bytesNeeded;
1774 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1775 pbEncoded, pcbEncoded, bytesNeeded)))
1777 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1778 pbEncoded = *(BYTE **)pbEncoded;
1779 *pbEncoded++ = ASN_SEQUENCEOF;
1780 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1782 pbEncoded += lenBytes;
1783 for (i = 0; ret && i < info->cRDN; i++)
1786 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1787 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1792 bytesNeeded -= size;
1801 SetLastError(STATUS_ACCESS_VIOLATION);
1808 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1809 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1810 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1812 BOOL val = *(const BOOL *)pvStructInfo, ret;
1821 else if (*pcbEncoded < 3)
1824 SetLastError(ERROR_MORE_DATA);
1830 *pbEncoded++ = ASN_BOOL;
1832 *pbEncoded++ = val ? 0xff : 0;
1835 TRACE("returning %d (%08x)\n", ret, GetLastError());
1839 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1840 BYTE *pbEncoded, DWORD *pcbEncoded)
1846 switch (entry->dwAltNameChoice)
1848 case CERT_ALT_NAME_RFC822_NAME:
1849 case CERT_ALT_NAME_DNS_NAME:
1850 case CERT_ALT_NAME_URL:
1851 if (entry->u.pwszURL)
1855 /* Not + 1: don't encode the NULL-terminator */
1856 dataLen = lstrlenW(entry->u.pwszURL);
1857 for (i = 0; ret && i < dataLen; i++)
1859 if (entry->u.pwszURL[i] > 0x7f)
1861 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1870 case CERT_ALT_NAME_IP_ADDRESS:
1871 dataLen = entry->u.IPAddress.cbData;
1873 case CERT_ALT_NAME_REGISTERED_ID:
1874 /* FIXME: encode OID */
1875 case CERT_ALT_NAME_OTHER_NAME:
1876 case CERT_ALT_NAME_DIRECTORY_NAME:
1877 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1880 SetLastError(E_INVALIDARG);
1885 DWORD bytesNeeded, lenBytes;
1887 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1888 bytesNeeded = 1 + dataLen + lenBytes;
1890 *pcbEncoded = bytesNeeded;
1891 else if (*pcbEncoded < bytesNeeded)
1893 SetLastError(ERROR_MORE_DATA);
1894 *pcbEncoded = bytesNeeded;
1899 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1900 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1901 pbEncoded += lenBytes;
1902 switch (entry->dwAltNameChoice)
1904 case CERT_ALT_NAME_RFC822_NAME:
1905 case CERT_ALT_NAME_DNS_NAME:
1906 case CERT_ALT_NAME_URL:
1910 for (i = 0; i < dataLen; i++)
1911 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1914 case CERT_ALT_NAME_IP_ADDRESS:
1915 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1919 *pcbEncoded = bytesNeeded;
1922 TRACE("returning %d (%08x)\n", ret, GetLastError());
1926 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
1927 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1928 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1934 const CERT_AUTHORITY_KEY_ID_INFO *info =
1935 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
1936 struct AsnEncodeSequenceItem items[3] = { { 0 } };
1937 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
1938 struct AsnConstructedItem constructed = { 0 };
1939 DWORD cItem = 0, cSwapped = 0;
1941 if (info->KeyId.cbData)
1943 swapped[cSwapped].tag = ASN_CONTEXT | 0;
1944 swapped[cSwapped].pvStructInfo = &info->KeyId;
1945 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1946 items[cItem].pvStructInfo = &swapped[cSwapped];
1947 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1951 if (info->CertIssuer.cbData)
1953 constructed.tag = 1;
1954 constructed.pvStructInfo = &info->CertIssuer;
1955 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1956 items[cItem].pvStructInfo = &constructed;
1957 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1960 if (info->CertSerialNumber.cbData)
1962 swapped[cSwapped].tag = ASN_CONTEXT | 2;
1963 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
1964 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1965 items[cItem].pvStructInfo = &swapped[cSwapped];
1966 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1970 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
1971 pEncodePara, pbEncoded, pcbEncoded);
1975 SetLastError(STATUS_ACCESS_VIOLATION);
1982 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1983 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1984 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1990 const CERT_ALT_NAME_INFO *info =
1991 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1992 DWORD bytesNeeded, dataLen, lenBytes, i;
1995 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1996 * can't encode an erroneous entry index if it's bigger than this.
1998 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2002 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2006 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2008 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2009 * the bad character, now set the index of the bad
2012 *pcbEncoded = (BYTE)i <<
2013 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2018 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2019 bytesNeeded = 1 + lenBytes + dataLen;
2022 *pcbEncoded = bytesNeeded;
2027 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2028 pbEncoded, pcbEncoded, bytesNeeded)))
2030 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2031 pbEncoded = *(BYTE **)pbEncoded;
2032 *pbEncoded++ = ASN_SEQUENCEOF;
2033 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2034 pbEncoded += lenBytes;
2035 for (i = 0; ret && i < info->cAltEntry; i++)
2037 DWORD len = dataLen;
2039 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2053 SetLastError(STATUS_ACCESS_VIOLATION);
2060 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2061 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2062 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2068 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2069 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2070 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2071 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2072 DWORD cItem = 0, cSwapped = 0;
2074 if (info->KeyId.cbData)
2076 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2077 swapped[cSwapped].pvStructInfo = &info->KeyId;
2078 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2079 items[cItem].pvStructInfo = &swapped[cSwapped];
2080 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2084 if (info->AuthorityCertIssuer.cAltEntry)
2086 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2087 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2088 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2089 items[cItem].pvStructInfo = &swapped[cSwapped];
2090 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2094 if (info->AuthorityCertSerialNumber.cbData)
2096 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2097 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2098 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2099 items[cItem].pvStructInfo = &swapped[cSwapped];
2100 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2104 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2105 pEncodePara, pbEncoded, pcbEncoded);
2109 SetLastError(STATUS_ACCESS_VIOLATION);
2116 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2117 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2118 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2124 const CERT_BASIC_CONSTRAINTS_INFO *info =
2125 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2126 struct AsnEncodeSequenceItem items[3] = {
2127 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2132 if (info->fPathLenConstraint)
2134 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2135 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2138 if (info->cSubtreesConstraint)
2140 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2141 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2144 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2145 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2149 SetLastError(STATUS_ACCESS_VIOLATION);
2156 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2157 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2158 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2164 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2165 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2166 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2171 items[cItem].pvStructInfo = &info->fCA;
2172 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2175 if (info->fPathLenConstraint)
2177 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2178 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2181 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2182 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2186 SetLastError(STATUS_ACCESS_VIOLATION);
2193 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2194 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2195 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2201 const BLOBHEADER *hdr =
2202 (const BLOBHEADER *)pvStructInfo;
2204 if (hdr->bType != PUBLICKEYBLOB)
2206 SetLastError(E_INVALIDARG);
2211 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2212 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2213 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2214 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2215 struct AsnEncodeSequenceItem items[] = {
2216 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2217 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2220 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2221 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2227 SetLastError(STATUS_ACCESS_VIOLATION);
2234 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2235 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2236 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2242 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2243 DWORD bytesNeeded, lenBytes;
2245 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2246 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2248 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2249 bytesNeeded = 1 + lenBytes + blob->cbData;
2252 *pcbEncoded = bytesNeeded;
2257 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2258 pcbEncoded, bytesNeeded)))
2260 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2261 pbEncoded = *(BYTE **)pbEncoded;
2262 *pbEncoded++ = ASN_OCTETSTRING;
2263 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2264 pbEncoded += lenBytes;
2266 memcpy(pbEncoded, blob->pbData, blob->cbData);
2272 SetLastError(STATUS_ACCESS_VIOLATION);
2276 TRACE("returning %d (%08x)\n", ret, GetLastError());
2280 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2281 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2282 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2288 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2289 DWORD bytesNeeded, lenBytes, dataBytes;
2292 /* yep, MS allows cUnusedBits to be >= 8 */
2293 if (!blob->cUnusedBits)
2295 dataBytes = blob->cbData;
2298 else if (blob->cbData * 8 > blob->cUnusedBits)
2300 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2301 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2309 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2310 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2313 *pcbEncoded = bytesNeeded;
2318 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2319 pcbEncoded, bytesNeeded)))
2321 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2322 pbEncoded = *(BYTE **)pbEncoded;
2323 *pbEncoded++ = ASN_BITSTRING;
2324 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2325 pbEncoded += lenBytes;
2326 *pbEncoded++ = unusedBits;
2329 BYTE mask = 0xff << unusedBits;
2333 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2334 pbEncoded += dataBytes - 1;
2336 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2343 SetLastError(STATUS_ACCESS_VIOLATION);
2350 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2358 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2359 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2364 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2369 for (i = 0; i < newBlob.cbData; i++)
2370 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2376 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2377 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2378 CryptMemFree(newBlob.pbData);
2382 SetLastError(STATUS_ACCESS_VIOLATION);
2389 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2390 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2391 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2393 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2395 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2396 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2399 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2400 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2401 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2407 DWORD significantBytes, lenBytes;
2408 BYTE padByte = 0, bytesNeeded;
2410 const CRYPT_INTEGER_BLOB *blob =
2411 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2413 significantBytes = blob->cbData;
2414 if (significantBytes)
2416 if (blob->pbData[significantBytes - 1] & 0x80)
2418 /* negative, lop off leading (little-endian) 0xffs */
2419 for (; significantBytes > 0 &&
2420 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2422 if (blob->pbData[significantBytes - 1] < 0x80)
2430 /* positive, lop off leading (little-endian) zeroes */
2431 for (; significantBytes > 0 &&
2432 !blob->pbData[significantBytes - 1]; significantBytes--)
2434 if (significantBytes == 0)
2435 significantBytes = 1;
2436 if (blob->pbData[significantBytes - 1] > 0x7f)
2444 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2446 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2447 bytesNeeded = 1 + lenBytes + significantBytes;
2452 *pcbEncoded = bytesNeeded;
2457 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2458 pcbEncoded, bytesNeeded)))
2460 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2461 pbEncoded = *(BYTE **)pbEncoded;
2462 *pbEncoded++ = ASN_INTEGER;
2465 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2466 pbEncoded += lenBytes;
2467 *pbEncoded++ = padByte;
2471 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2472 pbEncoded += lenBytes;
2474 for (; significantBytes > 0; significantBytes--)
2475 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2481 SetLastError(STATUS_ACCESS_VIOLATION);
2488 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2489 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2490 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2496 DWORD significantBytes, lenBytes;
2499 const CRYPT_INTEGER_BLOB *blob =
2500 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2502 significantBytes = blob->cbData;
2503 if (significantBytes)
2505 /* positive, lop off leading (little-endian) zeroes */
2506 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2509 if (significantBytes == 0)
2510 significantBytes = 1;
2511 if (blob->pbData[significantBytes - 1] > 0x7f)
2515 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2517 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2518 bytesNeeded = 1 + lenBytes + significantBytes;
2523 *pcbEncoded = bytesNeeded;
2528 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2529 pcbEncoded, bytesNeeded)))
2531 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2532 pbEncoded = *(BYTE **)pbEncoded;
2533 *pbEncoded++ = ASN_INTEGER;
2536 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2537 pbEncoded += lenBytes;
2542 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2543 pbEncoded += lenBytes;
2545 for (; significantBytes > 0; significantBytes--)
2546 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2552 SetLastError(STATUS_ACCESS_VIOLATION);
2559 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2560 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2561 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2563 CRYPT_INTEGER_BLOB blob;
2566 /* Encode as an unsigned integer, then change the tag to enumerated */
2567 blob.cbData = sizeof(DWORD);
2568 blob.pbData = (BYTE *)pvStructInfo;
2569 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2570 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2571 if (ret && pbEncoded)
2573 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2574 pbEncoded = *(BYTE **)pbEncoded;
2575 pbEncoded[0] = ASN_ENUMERATED;
2580 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2581 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2582 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2589 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2590 * temporary buffer because the output buffer is not NULL-terminated.
2593 static const DWORD bytesNeeded = sizeof(buf) - 1;
2597 *pcbEncoded = bytesNeeded;
2602 /* Sanity check the year, this is a two-digit year format */
2603 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2605 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2607 SetLastError(CRYPT_E_BAD_ENCODE);
2612 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2613 pbEncoded, pcbEncoded, bytesNeeded)))
2615 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2616 pbEncoded = *(BYTE **)pbEncoded;
2617 buf[0] = ASN_UTCTIME;
2618 buf[1] = bytesNeeded - 2;
2619 snprintf(buf + 2, sizeof(buf) - 2,
2620 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2621 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2622 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2623 sysTime.wMinute, sysTime.wSecond);
2624 memcpy(pbEncoded, buf, bytesNeeded);
2631 SetLastError(STATUS_ACCESS_VIOLATION);
2638 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2639 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2640 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2647 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2648 * temporary buffer because the output buffer is not NULL-terminated.
2651 static const DWORD bytesNeeded = sizeof(buf) - 1;
2655 *pcbEncoded = bytesNeeded;
2660 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2663 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2664 pcbEncoded, bytesNeeded);
2667 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2668 pbEncoded = *(BYTE **)pbEncoded;
2669 buf[0] = ASN_GENERALTIME;
2670 buf[1] = bytesNeeded - 2;
2671 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2672 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2673 sysTime.wMinute, sysTime.wSecond);
2674 memcpy(pbEncoded, buf, bytesNeeded);
2680 SetLastError(STATUS_ACCESS_VIOLATION);
2687 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2688 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2689 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2697 /* Check the year, if it's in the UTCTime range call that encode func */
2698 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2700 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2701 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2702 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2704 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2705 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2710 SetLastError(STATUS_ACCESS_VIOLATION);
2717 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2718 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2719 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2725 DWORD bytesNeeded, dataLen, lenBytes, i;
2726 const CRYPT_SEQUENCE_OF_ANY *seq =
2727 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2729 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2730 dataLen += seq->rgValue[i].cbData;
2731 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2732 bytesNeeded = 1 + lenBytes + dataLen;
2735 *pcbEncoded = bytesNeeded;
2740 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2741 pcbEncoded, bytesNeeded)))
2743 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2744 pbEncoded = *(BYTE **)pbEncoded;
2745 *pbEncoded++ = ASN_SEQUENCEOF;
2746 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2747 pbEncoded += lenBytes;
2748 for (i = 0; i < seq->cValue; i++)
2750 memcpy(pbEncoded, seq->rgValue[i].pbData,
2751 seq->rgValue[i].cbData);
2752 pbEncoded += seq->rgValue[i].cbData;
2759 SetLastError(STATUS_ACCESS_VIOLATION);
2766 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2767 BYTE *pbEncoded, DWORD *pcbEncoded)
2770 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2771 struct AsnConstructedItem constructed = { 0 };
2772 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2773 DWORD cItem = 0, cSwapped = 0;
2775 switch (distPoint->DistPointName.dwDistPointNameChoice)
2777 case CRL_DIST_POINT_NO_NAME:
2780 case CRL_DIST_POINT_FULL_NAME:
2781 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2782 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2783 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2784 constructed.tag = 0;
2785 constructed.pvStructInfo = &swapped[cSwapped];
2786 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2787 items[cItem].pvStructInfo = &constructed;
2788 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2792 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2793 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2799 if (ret && distPoint->ReasonFlags.cbData)
2801 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2802 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2803 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2804 items[cItem].pvStructInfo = &swapped[cSwapped];
2805 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2809 if (ret && distPoint->CRLIssuer.cAltEntry)
2811 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2812 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2813 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2814 items[cItem].pvStructInfo = &swapped[cSwapped];
2815 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2820 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2821 pbEncoded, pcbEncoded);
2825 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2826 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2827 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2833 const CRL_DIST_POINTS_INFO *info =
2834 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2836 if (!info->cDistPoint)
2838 SetLastError(E_INVALIDARG);
2843 DWORD bytesNeeded, dataLen, lenBytes, i;
2846 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2850 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2854 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2856 /* Have to propagate index of failing character */
2862 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2863 bytesNeeded = 1 + lenBytes + dataLen;
2866 *pcbEncoded = bytesNeeded;
2871 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2872 pbEncoded, pcbEncoded, bytesNeeded)))
2874 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2875 pbEncoded = *(BYTE **)pbEncoded;
2876 *pbEncoded++ = ASN_SEQUENCEOF;
2877 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2878 pbEncoded += lenBytes;
2879 for (i = 0; ret && i < info->cDistPoint; i++)
2881 DWORD len = dataLen;
2883 ret = CRYPT_AsnEncodeDistPoint(
2884 &info->rgDistPoint[i], pbEncoded, &len);
2898 SetLastError(STATUS_ACCESS_VIOLATION);
2905 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2906 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2907 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2913 const CERT_ENHKEY_USAGE *usage =
2914 (const CERT_ENHKEY_USAGE *)pvStructInfo;
2915 DWORD bytesNeeded = 0, lenBytes, size, i;
2918 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2920 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2921 usage->rgpszUsageIdentifier[i],
2922 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2924 bytesNeeded += size;
2926 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2927 bytesNeeded += 1 + lenBytes;
2931 *pcbEncoded = bytesNeeded;
2934 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2935 pbEncoded, pcbEncoded, bytesNeeded)))
2937 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2938 pbEncoded = *(BYTE **)pbEncoded;
2939 *pbEncoded++ = ASN_SEQUENCEOF;
2940 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2942 pbEncoded += lenBytes;
2943 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2946 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2947 usage->rgpszUsageIdentifier[i],
2948 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2953 bytesNeeded -= size;
2962 SetLastError(STATUS_ACCESS_VIOLATION);
2969 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
2970 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2971 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2977 const CRL_ISSUING_DIST_POINT *point =
2978 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
2979 struct AsnEncodeSequenceItem items[6] = { { 0 } };
2980 struct AsnConstructedItem constructed = { 0 };
2981 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
2982 DWORD cItem = 0, cSwapped = 0;
2985 switch (point->DistPointName.dwDistPointNameChoice)
2987 case CRL_DIST_POINT_NO_NAME:
2990 case CRL_DIST_POINT_FULL_NAME:
2991 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2992 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
2993 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2994 constructed.tag = 0;
2995 constructed.pvStructInfo = &swapped[cSwapped];
2996 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2997 items[cItem].pvStructInfo = &constructed;
2998 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3003 SetLastError(E_INVALIDARG);
3006 if (ret && point->fOnlyContainsUserCerts)
3008 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3009 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3010 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3011 items[cItem].pvStructInfo = &swapped[cSwapped];
3012 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3016 if (ret && point->fOnlyContainsCACerts)
3018 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3019 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3020 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3021 items[cItem].pvStructInfo = &swapped[cSwapped];
3022 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3026 if (ret && point->OnlySomeReasonFlags.cbData)
3028 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3029 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3030 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3031 items[cItem].pvStructInfo = &swapped[cSwapped];
3032 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3036 if (ret && point->fIndirectCRL)
3038 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3039 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3040 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3041 items[cItem].pvStructInfo = &swapped[cSwapped];
3042 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3047 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3048 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3052 SetLastError(STATUS_ACCESS_VIOLATION);
3059 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3060 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3061 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3065 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3066 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3067 struct AsnEncodeSequenceItem items[] = {
3068 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3069 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3072 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3073 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3078 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3079 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3080 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3084 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3086 SetLastError(E_INVALIDARG);
3092 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3094 if (!info->Issuer.cbData)
3095 SetLastError(E_INVALIDARG);
3098 struct AsnEncodeSequenceItem items[7] = {
3099 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3100 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3101 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
3102 { &info->HashEncryptionAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
3106 if (info->AuthAttrs.cAttr)
3108 items[cItem].pvStructInfo = &info->AuthAttrs;
3109 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3112 if (info->UnauthAttrs.cAttr)
3114 items[cItem].pvStructInfo = &info->UnauthAttrs;
3115 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3118 items[cItem].pvStructInfo = &info->EncryptedHash;
3119 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3121 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3122 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3127 SetLastError(STATUS_ACCESS_VIOLATION);
3133 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3134 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3135 void *pvEncoded, DWORD *pcbEncoded)
3137 static HCRYPTOIDFUNCSET set = NULL;
3139 CryptEncodeObjectExFunc encodeFunc = NULL;
3140 HCRYPTOIDFUNCADDR hFunc = NULL;
3142 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3143 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3144 pvEncoded, pcbEncoded);
3146 if (!pvEncoded && !pcbEncoded)
3148 SetLastError(ERROR_INVALID_PARAMETER);
3151 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3152 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3154 SetLastError(ERROR_FILE_NOT_FOUND);
3158 SetLastError(NOERROR);
3159 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3160 *(BYTE **)pvEncoded = NULL;
3161 if (!HIWORD(lpszStructType))
3163 switch (LOWORD(lpszStructType))
3165 case (WORD)X509_CERT:
3166 encodeFunc = CRYPT_AsnEncodeCert;
3168 case (WORD)X509_CERT_TO_BE_SIGNED:
3169 encodeFunc = CRYPT_AsnEncodeCertInfo;
3171 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3172 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3174 case (WORD)X509_EXTENSIONS:
3175 encodeFunc = CRYPT_AsnEncodeExtensions;
3177 case (WORD)X509_NAME_VALUE:
3178 encodeFunc = CRYPT_AsnEncodeNameValue;
3180 case (WORD)X509_NAME:
3181 encodeFunc = CRYPT_AsnEncodeName;
3183 case (WORD)X509_PUBLIC_KEY_INFO:
3184 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3186 case (WORD)X509_AUTHORITY_KEY_ID:
3187 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3189 case (WORD)X509_ALTERNATE_NAME:
3190 encodeFunc = CRYPT_AsnEncodeAltName;
3192 case (WORD)X509_BASIC_CONSTRAINTS:
3193 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3195 case (WORD)X509_BASIC_CONSTRAINTS2:
3196 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3198 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3199 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3201 case (WORD)X509_UNICODE_NAME:
3202 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3204 case (WORD)PKCS_CONTENT_INFO:
3205 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3207 case (WORD)PKCS_ATTRIBUTE:
3208 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3210 case (WORD)X509_UNICODE_NAME_VALUE:
3211 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3213 case (WORD)X509_OCTET_STRING:
3214 encodeFunc = CRYPT_AsnEncodeOctets;
3216 case (WORD)X509_BITS:
3217 case (WORD)X509_KEY_USAGE:
3218 encodeFunc = CRYPT_AsnEncodeBits;
3220 case (WORD)X509_INTEGER:
3221 encodeFunc = CRYPT_AsnEncodeInt;
3223 case (WORD)X509_MULTI_BYTE_INTEGER:
3224 encodeFunc = CRYPT_AsnEncodeInteger;
3226 case (WORD)X509_MULTI_BYTE_UINT:
3227 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3229 case (WORD)X509_ENUMERATED:
3230 encodeFunc = CRYPT_AsnEncodeEnumerated;
3232 case (WORD)X509_CHOICE_OF_TIME:
3233 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3235 case (WORD)X509_AUTHORITY_KEY_ID2:
3236 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3238 case (WORD)X509_SEQUENCE_OF_ANY:
3239 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3241 case (WORD)PKCS_UTC_TIME:
3242 encodeFunc = CRYPT_AsnEncodeUtcTime;
3244 case (WORD)X509_CRL_DIST_POINTS:
3245 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3247 case (WORD)X509_ENHANCED_KEY_USAGE:
3248 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3250 case (WORD)PKCS_ATTRIBUTES:
3251 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3253 case (WORD)X509_ISSUING_DIST_POINT:
3254 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3256 case (WORD)PKCS7_SIGNER_INFO:
3257 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3260 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3263 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3264 encodeFunc = CRYPT_AsnEncodeExtensions;
3265 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3266 encodeFunc = CRYPT_AsnEncodeUtcTime;
3267 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3268 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3269 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3270 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3271 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3272 encodeFunc = CRYPT_AsnEncodeEnumerated;
3273 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3274 encodeFunc = CRYPT_AsnEncodeBits;
3275 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3276 encodeFunc = CRYPT_AsnEncodeOctets;
3277 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3278 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3279 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3280 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3281 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3282 encodeFunc = CRYPT_AsnEncodeAltName;
3283 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3284 encodeFunc = CRYPT_AsnEncodeAltName;
3285 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3286 encodeFunc = CRYPT_AsnEncodeAltName;
3287 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3288 encodeFunc = CRYPT_AsnEncodeAltName;
3289 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3290 encodeFunc = CRYPT_AsnEncodeAltName;
3291 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3292 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3293 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3294 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3295 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3296 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3298 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3299 debugstr_a(lpszStructType));
3303 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3304 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3305 (void **)&encodeFunc, &hFunc);
3308 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3309 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3311 SetLastError(ERROR_FILE_NOT_FOUND);
3313 CryptFreeOIDFunctionAddress(hFunc, 0);
3317 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3318 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3320 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3321 NULL, 0, NULL, pInfo, pcbInfo);
3324 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3325 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3326 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3330 static CHAR oid[] = szOID_RSA_RSA;
3332 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3333 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3336 if (!pszPublicKeyObjId)
3337 pszPublicKeyObjId = oid;
3338 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3342 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3345 LPBYTE pubKey = CryptMemAlloc(keySize);
3349 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3353 DWORD encodedLen = 0;
3355 ret = CryptEncodeObject(dwCertEncodingType,
3356 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3359 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3360 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3363 *pcbInfo = sizeNeeded;
3364 else if (*pcbInfo < sizeNeeded)
3366 SetLastError(ERROR_MORE_DATA);
3367 *pcbInfo = sizeNeeded;
3372 pInfo->Algorithm.pszObjId = (char *)pInfo +
3373 sizeof(CERT_PUBLIC_KEY_INFO);
3374 lstrcpyA(pInfo->Algorithm.pszObjId,
3376 pInfo->Algorithm.Parameters.cbData = 0;
3377 pInfo->Algorithm.Parameters.pbData = NULL;
3378 pInfo->PublicKey.pbData =
3379 (BYTE *)pInfo->Algorithm.pszObjId
3380 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3381 pInfo->PublicKey.cbData = encodedLen;
3382 pInfo->PublicKey.cUnusedBits = 0;
3383 ret = CryptEncodeObject(dwCertEncodingType,
3384 RSA_CSP_PUBLICKEYBLOB, pubKey,
3385 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3389 CryptMemFree(pubKey);
3394 CryptDestroyKey(key);
3399 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3400 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3401 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3403 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3404 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3405 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3407 static HCRYPTOIDFUNCSET set = NULL;
3409 ExportPublicKeyInfoExFunc exportFunc = NULL;
3410 HCRYPTOIDFUNCADDR hFunc = NULL;
3412 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3413 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3418 SetLastError(ERROR_INVALID_PARAMETER);
3422 if (pszPublicKeyObjId)
3425 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3427 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3428 0, (void **)&exportFunc, &hFunc);
3431 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3432 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3433 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3435 CryptFreeOIDFunctionAddress(hFunc, 0);
3439 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3440 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3442 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3446 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3447 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3448 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3451 DWORD pubKeySize = 0;
3453 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3454 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3456 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3457 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3460 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3464 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3465 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3468 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3470 CryptMemFree(pubKey);
3478 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3479 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3480 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3482 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3483 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3484 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3486 static HCRYPTOIDFUNCSET set = NULL;
3488 ImportPublicKeyInfoExFunc importFunc = NULL;
3489 HCRYPTOIDFUNCADDR hFunc = NULL;
3491 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3492 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3495 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3496 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3497 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3499 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3500 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3503 CryptFreeOIDFunctionAddress(hFunc, 0);