2 * Copyright 2005-2007 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 isn't
21 * implemented, 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
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
34 #include "wine/port.h"
41 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(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 CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
98 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
102 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
104 if (pEncodePara && pEncodePara->pfnAlloc)
105 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
107 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
108 if (!*(BYTE **)pbEncoded)
111 *pcbEncoded = bytesNeeded;
113 else if (bytesNeeded > *pcbEncoded)
115 *pcbEncoded = bytesNeeded;
116 SetLastError(ERROR_MORE_DATA);
120 *pcbEncoded = bytesNeeded;
124 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
126 DWORD bytesNeeded, significantBytes = 0;
134 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
135 temp <<= 8, significantBytes--)
137 bytesNeeded = significantBytes + 1;
141 *pcbEncoded = bytesNeeded;
144 if (*pcbEncoded < bytesNeeded)
146 SetLastError(ERROR_MORE_DATA);
150 *pbEncoded = (BYTE)len;
155 *pbEncoded++ = significantBytes | 0x80;
156 for (i = 0; i < significantBytes; i++)
158 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
162 *pcbEncoded = bytesNeeded;
166 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
167 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
168 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
171 DWORD i, dataLen = 0;
173 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
174 pbEncoded, *pcbEncoded);
175 for (i = 0, ret = TRUE; ret && i < cItem; i++)
177 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
178 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
179 NULL, &items[i].size);
180 /* Some functions propagate their errors through the size */
182 *pcbEncoded = items[i].size;
183 dataLen += items[i].size;
187 DWORD lenBytes, bytesNeeded;
189 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
190 bytesNeeded = 1 + lenBytes + dataLen;
192 *pcbEncoded = bytesNeeded;
195 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
196 pcbEncoded, bytesNeeded)))
198 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
199 pbEncoded = *(BYTE **)pbEncoded;
200 *pbEncoded++ = ASN_SEQUENCE;
201 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
202 pbEncoded += lenBytes;
203 for (i = 0; ret && i < cItem; i++)
205 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
206 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
207 NULL, pbEncoded, &items[i].size);
208 /* Some functions propagate their errors through the size */
210 *pcbEncoded = items[i].size;
211 pbEncoded += items[i].size;
216 TRACE("returning %d (%08x)\n", ret, GetLastError());
220 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
221 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
222 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
225 const struct AsnConstructedItem *item =
226 (const struct AsnConstructedItem *)pvStructInfo;
229 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
230 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
232 DWORD dataLen, bytesNeeded;
234 CRYPT_EncodeLen(len, NULL, &dataLen);
235 bytesNeeded = 1 + dataLen + len;
237 *pcbEncoded = bytesNeeded;
238 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
239 pbEncoded, pcbEncoded, bytesNeeded)))
241 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
242 pbEncoded = *(BYTE **)pbEncoded;
243 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
244 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
245 pbEncoded += dataLen;
246 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
247 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
251 /* Some functions propagate their errors through the size */
258 /* Some functions propagate their errors through the size */
264 struct AsnEncodeTagSwappedItem
267 const void *pvStructInfo;
268 CryptEncodeObjectExFunc encodeFunc;
271 /* Sort of a wacky hack, it encodes something using the struct
272 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
273 * given in the struct AsnEncodeTagSwappedItem.
275 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
276 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
277 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
280 const struct AsnEncodeTagSwappedItem *item =
281 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
283 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
284 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
285 if (ret && pbEncoded)
286 *pbEncoded = item->tag;
290 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
291 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
292 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
294 const DWORD *ver = (const DWORD *)pvStructInfo;
297 /* CERT_V1 is not encoded */
305 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
307 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
308 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
313 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
314 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
315 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
317 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
322 *pcbEncoded = blob->cbData;
327 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
328 pcbEncoded, blob->cbData)))
330 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
331 pbEncoded = *(BYTE **)pbEncoded;
333 memcpy(pbEncoded, blob->pbData, blob->cbData);
334 *pcbEncoded = blob->cbData;
341 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
346 /* This has two filetimes in a row, a NotBefore and a NotAfter */
347 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
348 struct AsnEncodeSequenceItem items[] = {
349 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
350 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
353 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
354 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
359 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
362 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
363 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
364 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
367 const CRYPT_ALGORITHM_IDENTIFIER *algo =
368 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
369 static const BYTE asn1Null[] = { ASN_NULL, 0 };
370 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
373 struct AsnEncodeSequenceItem items[2] = {
374 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
375 { NULL, CRYPT_CopyEncodedBlob, 0 },
378 if (algo->Parameters.cbData)
379 items[1].pvStructInfo = &algo->Parameters;
381 items[1].pvStructInfo = &nullBlob;
382 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
383 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
388 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
389 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
390 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
392 const CRYPT_ALGORITHM_IDENTIFIER *algo =
393 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
395 struct AsnEncodeSequenceItem items[] = {
396 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
397 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
400 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
401 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
406 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
407 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
408 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
414 const CERT_PUBLIC_KEY_INFO *info =
415 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
416 struct AsnEncodeSequenceItem items[] = {
417 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
418 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
421 TRACE("Encoding public key with OID %s\n",
422 debugstr_a(info->Algorithm.pszObjId));
423 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
424 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
429 SetLastError(STATUS_ACCESS_VIOLATION);
436 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
437 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
438 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
444 const CERT_SIGNED_CONTENT_INFO *info =
445 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
446 struct AsnEncodeSequenceItem items[] = {
447 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
448 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
449 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
452 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
453 items[2].encodeFunc = CRYPT_AsnEncodeBits;
454 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
455 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
460 SetLastError(STATUS_ACCESS_VIOLATION);
467 /* Like in Windows, this blithely ignores the validity of the passed-in
468 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
469 * decode properly, see CRYPT_AsnDecodeCertInfo.
471 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
479 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
480 struct AsnEncodeSequenceItem items[10] = {
481 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
482 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
485 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
486 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
487 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
490 struct AsnConstructedItem constructed[3] = { { 0 } };
491 DWORD cItem = 7, cConstructed = 0;
493 if (info->IssuerUniqueId.cbData)
495 constructed[cConstructed].tag = 1;
496 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
497 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
498 items[cItem].pvStructInfo = &constructed[cConstructed];
499 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
503 if (info->SubjectUniqueId.cbData)
505 constructed[cConstructed].tag = 2;
506 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
507 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
508 items[cItem].pvStructInfo = &constructed[cConstructed];
509 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
513 if (info->cExtension)
515 constructed[cConstructed].tag = 3;
516 constructed[cConstructed].pvStructInfo = &info->cExtension;
517 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
518 items[cItem].pvStructInfo = &constructed[cConstructed];
519 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
524 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
525 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
529 SetLastError(STATUS_ACCESS_VIOLATION);
536 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
537 BYTE *pbEncoded, DWORD *pcbEncoded)
539 struct AsnEncodeSequenceItem items[3] = {
540 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
541 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
547 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
549 if (entry->cExtension)
551 items[cItem].pvStructInfo = &entry->cExtension;
552 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
556 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
557 pbEncoded, pcbEncoded);
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
563 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
564 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
565 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
567 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
568 DWORD bytesNeeded, dataLen, lenBytes, i;
569 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
570 ((const BYTE *)pvStructInfo + sizeof(DWORD));
573 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
577 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
581 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
582 bytesNeeded = 1 + lenBytes + dataLen;
584 *pcbEncoded = bytesNeeded;
587 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
588 pcbEncoded, bytesNeeded)))
590 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
591 pbEncoded = *(BYTE **)pbEncoded;
592 *pbEncoded++ = ASN_SEQUENCEOF;
593 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
594 pbEncoded += lenBytes;
595 for (i = 0; i < cCRLEntry; i++)
597 DWORD size = dataLen;
599 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
608 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
609 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
610 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
612 const DWORD *ver = (const DWORD *)pvStructInfo;
615 /* CRL_V1 is not encoded */
622 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
623 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
627 /* Like in Windows, this blithely ignores the validity of the passed-in
628 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
629 * decode properly, see CRYPT_AsnDecodeCRLInfo.
631 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
632 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
633 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
639 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
640 struct AsnEncodeSequenceItem items[7] = {
641 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
642 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
643 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
644 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
647 struct AsnConstructedItem constructed[1] = { { 0 } };
648 DWORD cItem = 4, cConstructed = 0;
650 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
652 items[cItem].pvStructInfo = &info->NextUpdate;
653 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
658 items[cItem].pvStructInfo = &info->cCRLEntry;
659 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
662 if (info->cExtension)
664 constructed[cConstructed].tag = 0;
665 constructed[cConstructed].pvStructInfo = &info->cExtension;
666 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
667 items[cItem].pvStructInfo = &constructed[cConstructed];
668 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
673 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
674 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
678 SetLastError(STATUS_ACCESS_VIOLATION);
685 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
689 struct AsnEncodeSequenceItem items[3] = {
690 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
696 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
700 items[cItem].pvStructInfo = &ext->fCritical;
701 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
704 items[cItem].pvStructInfo = &ext->Value;
705 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
708 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
709 pbEncoded, pcbEncoded);
710 TRACE("returning %d (%08x)\n", ret, GetLastError());
714 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
716 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
722 DWORD bytesNeeded, dataLen, lenBytes, i;
723 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
726 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
730 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
734 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
735 bytesNeeded = 1 + lenBytes + dataLen;
737 *pcbEncoded = bytesNeeded;
740 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
741 pcbEncoded, bytesNeeded)))
743 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
744 pbEncoded = *(BYTE **)pbEncoded;
745 *pbEncoded++ = ASN_SEQUENCEOF;
746 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
747 pbEncoded += lenBytes;
748 for (i = 0; i < exts->cExtension; i++)
750 DWORD size = dataLen;
752 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
762 SetLastError(STATUS_ACCESS_VIOLATION);
769 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
770 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
771 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
773 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
774 DWORD bytesNeeded = 0, lenBytes;
779 TRACE("%s\n", debugstr_a(pszObjId));
786 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
788 SetLastError(CRYPT_E_ASN1_ERROR);
792 firstByte = val1 * 40 + val2;
793 ptr = pszObjId + firstPos;
798 /* note I assume each component is at most 32-bits long in base 2 */
799 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
801 if (val1 >= 0x10000000)
803 else if (val1 >= 0x200000)
805 else if (val1 >= 0x4000)
807 else if (val1 >= 0x80)
817 SetLastError(CRYPT_E_ASN1_ERROR);
821 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
825 bytesNeeded += 1 + lenBytes;
828 if (*pcbEncoded < bytesNeeded)
830 SetLastError(ERROR_MORE_DATA);
835 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
836 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
837 pbEncoded += lenBytes;
843 *pbEncoded++ = firstByte;
844 ptr = pszObjId + firstPos;
847 sscanf(ptr, "%d%n", &val, &pos);
849 unsigned char outBytes[5];
852 if (val >= 0x10000000)
854 else if (val >= 0x200000)
856 else if (val >= 0x4000)
858 else if (val >= 0x80)
862 for (i = numBytes; i > 0; i--)
864 outBytes[i - 1] = val & 0x7f;
867 for (i = 0; i < numBytes - 1; i++)
868 *pbEncoded++ = outBytes[i] | 0x80;
869 *pbEncoded++ = outBytes[i];
878 *pcbEncoded = bytesNeeded;
882 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
883 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
887 LPCSTR str = (LPCSTR)value->Value.pbData;
888 DWORD bytesNeeded, lenBytes, encodedLen;
890 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
891 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
892 bytesNeeded = 1 + lenBytes + encodedLen;
894 *pcbEncoded = bytesNeeded;
897 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
898 pbEncoded, pcbEncoded, bytesNeeded)))
900 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
901 pbEncoded = *(BYTE **)pbEncoded;
903 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
904 pbEncoded += lenBytes;
905 memcpy(pbEncoded, str, encodedLen);
911 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
912 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
916 LPCWSTR str = (LPCWSTR)value->Value.pbData;
917 DWORD bytesNeeded, lenBytes, strLen;
919 if (value->Value.cbData)
920 strLen = value->Value.cbData / sizeof(WCHAR);
921 else if (value->Value.pbData)
922 strLen = lstrlenW(str);
925 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
926 bytesNeeded = 1 + lenBytes + strLen * 2;
928 *pcbEncoded = bytesNeeded;
931 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
932 pbEncoded, pcbEncoded, bytesNeeded)))
936 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
937 pbEncoded = *(BYTE **)pbEncoded;
938 *pbEncoded++ = ASN_BMPSTRING;
939 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
940 pbEncoded += lenBytes;
941 for (i = 0; i < strLen; i++)
943 *pbEncoded++ = (str[i] & 0xff00) >> 8;
944 *pbEncoded++ = str[i] & 0x00ff;
951 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
952 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
956 LPCWSTR str = (LPCWSTR)value->Value.pbData;
957 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
959 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
961 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
963 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
964 bytesNeeded = 1 + lenBytes + encodedLen;
966 *pcbEncoded = bytesNeeded;
969 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
970 pbEncoded, pcbEncoded, bytesNeeded)))
972 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
973 pbEncoded = *(BYTE **)pbEncoded;
974 *pbEncoded++ = ASN_UTF8STRING;
975 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
976 pbEncoded += lenBytes;
977 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
978 bytesNeeded - lenBytes - 1, NULL, NULL);
984 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
985 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
986 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
992 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
994 switch (value->dwValueType)
996 case CERT_RDN_ANY_TYPE:
997 /* explicitly disallowed */
998 SetLastError(E_INVALIDARG);
1001 case CERT_RDN_ENCODED_BLOB:
1002 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1003 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1005 case CERT_RDN_OCTET_STRING:
1006 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1007 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1009 case CERT_RDN_NUMERIC_STRING:
1010 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1011 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1013 case CERT_RDN_PRINTABLE_STRING:
1014 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1015 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1017 case CERT_RDN_TELETEX_STRING:
1018 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1019 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1021 case CERT_RDN_VIDEOTEX_STRING:
1022 ret = CRYPT_AsnEncodeStringCoerce(value,
1023 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1025 case CERT_RDN_IA5_STRING:
1026 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1027 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1029 case CERT_RDN_GRAPHIC_STRING:
1030 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1031 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1033 case CERT_RDN_VISIBLE_STRING:
1034 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1035 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1037 case CERT_RDN_GENERAL_STRING:
1038 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1039 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1041 case CERT_RDN_UNIVERSAL_STRING:
1042 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1043 SetLastError(CRYPT_E_ASN1_CHOICE);
1046 case CERT_RDN_BMP_STRING:
1047 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1048 pbEncoded, pcbEncoded);
1050 case CERT_RDN_UTF8_STRING:
1051 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1052 pbEncoded, pcbEncoded);
1055 SetLastError(CRYPT_E_ASN1_CHOICE);
1061 SetLastError(STATUS_ACCESS_VIOLATION);
1068 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1069 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1070 BYTE *pbEncoded, DWORD *pcbEncoded)
1072 DWORD bytesNeeded = 0, lenBytes, size;
1075 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1076 0, NULL, NULL, &size);
1079 bytesNeeded += size;
1080 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1081 * with dwValueType, so "cast" it to get its encoded size
1083 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1084 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1087 bytesNeeded += size;
1088 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1089 bytesNeeded += 1 + lenBytes;
1092 if (*pcbEncoded < bytesNeeded)
1094 SetLastError(ERROR_MORE_DATA);
1099 *pbEncoded++ = ASN_SEQUENCE;
1100 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1102 pbEncoded += lenBytes;
1103 size = bytesNeeded - 1 - lenBytes;
1104 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1105 attr->pszObjId, 0, NULL, pbEncoded, &size);
1109 size = bytesNeeded - 1 - lenBytes - size;
1110 ret = nameValueEncodeFunc(dwCertEncodingType,
1111 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1112 0, NULL, pbEncoded, &size);
1119 *pcbEncoded = bytesNeeded;
1123 /* Have to propagate index of failing character */
1130 static int BLOBComp(const void *l, const void *r)
1132 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1135 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1136 ret = a->cbData - b->cbData;
1140 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1142 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1143 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1144 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1146 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1147 DWORD bytesNeeded = 0, lenBytes, i;
1150 for (i = 0; i < set->cBlob; i++)
1151 bytesNeeded += set->rgBlob[i].cbData;
1152 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1153 bytesNeeded += 1 + lenBytes;
1156 *pcbEncoded = bytesNeeded;
1159 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1160 pbEncoded, pcbEncoded, bytesNeeded)))
1162 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1163 pbEncoded = *(BYTE **)pbEncoded;
1164 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1165 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1166 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1167 pbEncoded += lenBytes;
1168 for (i = 0; ret && i < set->cBlob; i++)
1170 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1171 pbEncoded += set->rgBlob[i].cbData;
1177 struct DERSetDescriptor
1183 CryptEncodeObjectExFunc encode;
1186 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1187 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1188 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1190 const struct DERSetDescriptor *desc =
1191 (const struct DERSetDescriptor *)pvStructInfo;
1192 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1198 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1203 setOf.cBlob = desc->cItems;
1204 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1207 for (i = 0; ret && i < setOf.cBlob; i++)
1209 ret = desc->encode(dwCertEncodingType, lpszStructType,
1210 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1211 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1214 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1215 if (!setOf.rgBlob[i].pbData)
1218 ret = desc->encode(dwCertEncodingType, lpszStructType,
1219 (const BYTE *)desc->items + i * desc->itemSize +
1220 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1221 &setOf.rgBlob[i].cbData);
1223 /* Some functions propagate their errors through the size */
1225 *pcbEncoded = setOf.rgBlob[i].cbData;
1229 DWORD bytesNeeded = 0, lenBytes;
1232 for (i = 0; i < setOf.cBlob; i++)
1233 bytesNeeded += setOf.rgBlob[i].cbData;
1234 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1235 bytesNeeded += 1 + lenBytes;
1237 *pcbEncoded = bytesNeeded;
1238 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1239 pbEncoded, pcbEncoded, bytesNeeded)))
1241 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1242 pbEncoded = *(BYTE **)pbEncoded;
1243 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1245 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1246 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1247 pbEncoded += lenBytes;
1248 for (i = 0; i < setOf.cBlob; i++)
1250 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1251 setOf.rgBlob[i].cbData);
1252 pbEncoded += setOf.rgBlob[i].cbData;
1256 for (i = 0; i < setOf.cBlob; i++)
1257 CryptMemFree(setOf.rgBlob[i].pbData);
1258 CryptMemFree(setOf.rgBlob);
1262 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1263 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1267 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1276 setOf.cBlob = rdn->cRDNAttr;
1277 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1278 sizeof(CRYPT_DER_BLOB));
1282 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1284 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1286 setOf.rgBlob[i].cbData = 0;
1287 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1288 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1291 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1292 if (!setOf.rgBlob[i].pbData)
1295 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1296 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1297 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1301 /* Have to propagate index of failing character */
1302 *pcbEncoded = setOf.rgBlob[i].cbData;
1306 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1307 pbEncoded, pcbEncoded);
1308 for (i = 0; i < setOf.cBlob; i++)
1309 CryptMemFree(setOf.rgBlob[i].pbData);
1313 SetLastError(STATUS_ACCESS_VIOLATION);
1317 CryptMemFree(setOf.rgBlob);
1321 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1322 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1323 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1325 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1326 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1327 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1330 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1333 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1334 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1335 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1337 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1338 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1342 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1343 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1344 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1350 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1351 DWORD bytesNeeded = 0, lenBytes, size, i;
1353 TRACE("encoding name with %d RDNs\n", info->cRDN);
1355 for (i = 0; ret && i < info->cRDN; i++)
1357 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1358 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1360 bytesNeeded += size;
1364 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1365 bytesNeeded += 1 + lenBytes;
1369 *pcbEncoded = bytesNeeded;
1372 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1373 pbEncoded, pcbEncoded, bytesNeeded)))
1375 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1376 pbEncoded = *(BYTE **)pbEncoded;
1377 *pbEncoded++ = ASN_SEQUENCEOF;
1378 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1380 pbEncoded += lenBytes;
1381 for (i = 0; ret && i < info->cRDN; i++)
1384 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1385 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1390 bytesNeeded -= size;
1401 SetLastError(STATUS_ACCESS_VIOLATION);
1408 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1416 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1418 if (!attr->pszObjId)
1419 SetLastError(E_INVALIDARG);
1422 struct AsnEncodeSequenceItem items[2] = {
1423 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1424 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1427 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1428 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1434 SetLastError(STATUS_ACCESS_VIOLATION);
1440 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1448 const CRYPT_ATTRIBUTES *attributes =
1449 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1450 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1451 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1453 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1454 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1458 SetLastError(STATUS_ACCESS_VIOLATION);
1464 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1465 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1466 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1467 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1470 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1471 struct AsnEncodeSequenceItem items[2] = {
1472 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1475 struct AsnConstructedItem constructed = { 0 };
1478 if (info->Content.cbData)
1480 constructed.tag = 0;
1481 constructed.pvStructInfo = &info->Content;
1482 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1483 items[cItem].pvStructInfo = &constructed;
1484 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1487 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1488 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1491 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1492 void *pvData, DWORD *pcbData)
1494 struct AsnEncodeSequenceItem items[] = {
1495 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1496 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1498 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1499 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1502 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1503 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1506 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1514 const CRYPT_CONTENT_INFO *info =
1515 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1517 if (!info->pszObjId)
1518 SetLastError(E_INVALIDARG);
1520 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1521 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1526 SetLastError(STATUS_ACCESS_VIOLATION);
1532 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1533 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1537 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1538 DWORD bytesNeeded, lenBytes, encodedLen;
1540 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1542 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1543 bytesNeeded = 1 + lenBytes + encodedLen;
1545 *pcbEncoded = bytesNeeded;
1548 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1549 pbEncoded, pcbEncoded, bytesNeeded)))
1553 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1554 pbEncoded = *(BYTE **)pbEncoded;
1556 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1557 pbEncoded += lenBytes;
1558 for (i = 0; i < encodedLen; i++)
1559 *pbEncoded++ = (BYTE)str[i];
1565 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1566 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1570 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1571 DWORD bytesNeeded, lenBytes, encodedLen;
1573 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1575 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1576 bytesNeeded = 1 + lenBytes + encodedLen;
1578 *pcbEncoded = bytesNeeded;
1581 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1582 pbEncoded, pcbEncoded, bytesNeeded)))
1587 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1588 ptr = *(BYTE **)pbEncoded;
1591 *ptr++ = ASN_NUMERICSTRING;
1592 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1594 for (i = 0; ret && i < encodedLen; i++)
1596 if (isdigitW(str[i]))
1597 *ptr++ = (BYTE)str[i];
1601 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1605 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1606 CryptMemFree(*(BYTE **)pbEncoded);
1612 static inline int isprintableW(WCHAR wc)
1614 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1615 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1616 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1619 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1620 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1624 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1625 DWORD bytesNeeded, lenBytes, encodedLen;
1627 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1629 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1630 bytesNeeded = 1 + lenBytes + encodedLen;
1632 *pcbEncoded = bytesNeeded;
1635 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1636 pbEncoded, pcbEncoded, bytesNeeded)))
1641 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1642 ptr = *(BYTE **)pbEncoded;
1645 *ptr++ = ASN_PRINTABLESTRING;
1646 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1648 for (i = 0; ret && i < encodedLen; i++)
1650 if (isprintableW(str[i]))
1651 *ptr++ = (BYTE)str[i];
1655 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1659 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1660 CryptMemFree(*(BYTE **)pbEncoded);
1666 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1667 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1671 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1672 DWORD bytesNeeded, lenBytes, encodedLen;
1674 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1676 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1677 bytesNeeded = 1 + lenBytes + encodedLen;
1679 *pcbEncoded = bytesNeeded;
1682 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1683 pbEncoded, pcbEncoded, bytesNeeded)))
1688 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1689 ptr = *(BYTE **)pbEncoded;
1692 *ptr++ = ASN_IA5STRING;
1693 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1695 for (i = 0; ret && i < encodedLen; i++)
1698 *ptr++ = (BYTE)str[i];
1702 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1706 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1707 CryptMemFree(*(BYTE **)pbEncoded);
1713 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1714 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1718 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1719 DWORD bytesNeeded, lenBytes, strLen;
1721 /* FIXME: doesn't handle composite characters */
1722 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1724 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1725 bytesNeeded = 1 + lenBytes + strLen * 4;
1727 *pcbEncoded = bytesNeeded;
1730 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1731 pbEncoded, pcbEncoded, bytesNeeded)))
1735 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1736 pbEncoded = *(BYTE **)pbEncoded;
1737 *pbEncoded++ = ASN_UNIVERSALSTRING;
1738 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1739 pbEncoded += lenBytes;
1740 for (i = 0; i < strLen; i++)
1744 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1745 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1752 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1753 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1754 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1760 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1762 switch (value->dwValueType)
1764 case CERT_RDN_ANY_TYPE:
1765 case CERT_RDN_ENCODED_BLOB:
1766 case CERT_RDN_OCTET_STRING:
1767 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1769 case CERT_RDN_NUMERIC_STRING:
1770 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1771 pbEncoded, pcbEncoded);
1773 case CERT_RDN_PRINTABLE_STRING:
1774 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1775 pbEncoded, pcbEncoded);
1777 case CERT_RDN_TELETEX_STRING:
1778 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1779 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1781 case CERT_RDN_VIDEOTEX_STRING:
1782 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1783 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1785 case CERT_RDN_IA5_STRING:
1786 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1787 pbEncoded, pcbEncoded);
1789 case CERT_RDN_GRAPHIC_STRING:
1790 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1791 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1793 case CERT_RDN_VISIBLE_STRING:
1794 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1795 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1797 case CERT_RDN_GENERAL_STRING:
1798 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1799 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1801 case CERT_RDN_UNIVERSAL_STRING:
1802 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1803 pbEncoded, pcbEncoded);
1805 case CERT_RDN_BMP_STRING:
1806 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1807 pbEncoded, pcbEncoded);
1809 case CERT_RDN_UTF8_STRING:
1810 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1811 pbEncoded, pcbEncoded);
1814 SetLastError(CRYPT_E_ASN1_CHOICE);
1819 SetLastError(STATUS_ACCESS_VIOLATION);
1825 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1826 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1827 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1833 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1834 DWORD bytesNeeded = 0, lenBytes, size, i;
1836 TRACE("encoding name with %d RDNs\n", info->cRDN);
1838 for (i = 0; ret && i < info->cRDN; i++)
1840 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1841 CRYPT_AsnEncodeNameValue, NULL, &size);
1843 bytesNeeded += size;
1845 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1846 bytesNeeded += 1 + lenBytes;
1850 *pcbEncoded = bytesNeeded;
1853 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1854 pbEncoded, pcbEncoded, bytesNeeded)))
1856 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1857 pbEncoded = *(BYTE **)pbEncoded;
1858 *pbEncoded++ = ASN_SEQUENCEOF;
1859 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1861 pbEncoded += lenBytes;
1862 for (i = 0; ret && i < info->cRDN; i++)
1865 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1866 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1871 bytesNeeded -= size;
1880 SetLastError(STATUS_ACCESS_VIOLATION);
1887 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1888 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1889 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1891 BOOL val = *(const BOOL *)pvStructInfo, ret;
1900 else if (*pcbEncoded < 3)
1903 SetLastError(ERROR_MORE_DATA);
1909 *pbEncoded++ = ASN_BOOL;
1911 *pbEncoded++ = val ? 0xff : 0;
1914 TRACE("returning %d (%08x)\n", ret, GetLastError());
1918 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1919 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1920 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1922 const CERT_ALT_NAME_ENTRY *entry =
1923 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1929 switch (entry->dwAltNameChoice)
1931 case CERT_ALT_NAME_RFC822_NAME:
1932 case CERT_ALT_NAME_DNS_NAME:
1933 case CERT_ALT_NAME_URL:
1934 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1935 if (entry->u.pwszURL)
1939 /* Not + 1: don't encode the NULL-terminator */
1940 dataLen = lstrlenW(entry->u.pwszURL);
1941 for (i = 0; ret && i < dataLen; i++)
1943 if (entry->u.pwszURL[i] > 0x7f)
1945 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1954 case CERT_ALT_NAME_DIRECTORY_NAME:
1955 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1956 dataLen = entry->u.DirectoryName.cbData;
1958 case CERT_ALT_NAME_IP_ADDRESS:
1959 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1960 dataLen = entry->u.IPAddress.cbData;
1962 case CERT_ALT_NAME_REGISTERED_ID:
1964 struct AsnEncodeTagSwappedItem swapped =
1965 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1966 CRYPT_AsnEncodeOid };
1968 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1971 case CERT_ALT_NAME_OTHER_NAME:
1972 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1975 SetLastError(E_INVALIDARG);
1980 DWORD bytesNeeded, lenBytes;
1982 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1983 bytesNeeded = 1 + dataLen + lenBytes;
1985 *pcbEncoded = bytesNeeded;
1986 else if (*pcbEncoded < bytesNeeded)
1988 SetLastError(ERROR_MORE_DATA);
1989 *pcbEncoded = bytesNeeded;
1995 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1996 pbEncoded += lenBytes;
1997 switch (entry->dwAltNameChoice)
1999 case CERT_ALT_NAME_RFC822_NAME:
2000 case CERT_ALT_NAME_DNS_NAME:
2001 case CERT_ALT_NAME_URL:
2005 for (i = 0; i < dataLen; i++)
2006 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2009 case CERT_ALT_NAME_DIRECTORY_NAME:
2010 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2012 case CERT_ALT_NAME_IP_ADDRESS:
2013 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2017 *pcbEncoded = bytesNeeded;
2020 TRACE("returning %d (%08x)\n", ret, GetLastError());
2024 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2025 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2026 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2032 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2033 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2038 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2043 for (i = 0; i < newBlob.cbData; i++)
2044 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2050 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2051 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2052 CryptMemFree(newBlob.pbData);
2056 SetLastError(STATUS_ACCESS_VIOLATION);
2063 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2064 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2065 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2071 const CERT_AUTHORITY_KEY_ID_INFO *info =
2072 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2073 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2074 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2075 struct AsnConstructedItem constructed = { 0 };
2076 DWORD cItem = 0, cSwapped = 0;
2078 if (info->KeyId.cbData)
2080 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2081 swapped[cSwapped].pvStructInfo = &info->KeyId;
2082 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2083 items[cItem].pvStructInfo = &swapped[cSwapped];
2084 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2088 if (info->CertIssuer.cbData)
2090 constructed.tag = 1;
2091 constructed.pvStructInfo = &info->CertIssuer;
2092 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2093 items[cItem].pvStructInfo = &constructed;
2094 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2097 if (info->CertSerialNumber.cbData)
2099 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2100 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2101 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2102 items[cItem].pvStructInfo = &swapped[cSwapped];
2103 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2107 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2108 pEncodePara, pbEncoded, pcbEncoded);
2112 SetLastError(STATUS_ACCESS_VIOLATION);
2119 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2120 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2121 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2127 const CERT_ALT_NAME_INFO *info =
2128 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2129 DWORD bytesNeeded, dataLen, lenBytes, i;
2132 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2133 * can't encode an erroneous entry index if it's bigger than this.
2135 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2139 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2140 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2143 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2145 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2146 * the bad character, now set the index of the bad
2149 *pcbEncoded = (BYTE)i <<
2150 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2155 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2156 bytesNeeded = 1 + lenBytes + dataLen;
2159 *pcbEncoded = bytesNeeded;
2164 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2165 pbEncoded, pcbEncoded, bytesNeeded)))
2167 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2168 pbEncoded = *(BYTE **)pbEncoded;
2169 *pbEncoded++ = ASN_SEQUENCEOF;
2170 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2171 pbEncoded += lenBytes;
2172 for (i = 0; ret && i < info->cAltEntry; i++)
2174 DWORD len = dataLen;
2176 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2177 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2190 SetLastError(STATUS_ACCESS_VIOLATION);
2197 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2198 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2199 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2205 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2206 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2207 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2208 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2209 DWORD cItem = 0, cSwapped = 0;
2211 if (info->KeyId.cbData)
2213 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2214 swapped[cSwapped].pvStructInfo = &info->KeyId;
2215 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2216 items[cItem].pvStructInfo = &swapped[cSwapped];
2217 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2221 if (info->AuthorityCertIssuer.cAltEntry)
2223 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2224 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2225 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2226 items[cItem].pvStructInfo = &swapped[cSwapped];
2227 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2231 if (info->AuthorityCertSerialNumber.cbData)
2233 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2234 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2235 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2236 items[cItem].pvStructInfo = &swapped[cSwapped];
2237 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2241 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2242 pEncodePara, pbEncoded, pcbEncoded);
2246 SetLastError(STATUS_ACCESS_VIOLATION);
2253 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2254 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2255 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2261 const CERT_BASIC_CONSTRAINTS_INFO *info =
2262 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2263 struct AsnEncodeSequenceItem items[3] = {
2264 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2269 if (info->fPathLenConstraint)
2271 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2272 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2275 if (info->cSubtreesConstraint)
2277 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2278 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2281 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2282 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2286 SetLastError(STATUS_ACCESS_VIOLATION);
2293 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2294 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2295 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2301 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2302 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2303 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2308 items[cItem].pvStructInfo = &info->fCA;
2309 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2312 if (info->fPathLenConstraint)
2314 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2315 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2318 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2319 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2323 SetLastError(STATUS_ACCESS_VIOLATION);
2330 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2331 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2332 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2338 const BLOBHEADER *hdr =
2339 (const BLOBHEADER *)pvStructInfo;
2341 if (hdr->bType != PUBLICKEYBLOB)
2343 SetLastError(E_INVALIDARG);
2348 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2349 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2350 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2351 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2352 struct AsnEncodeSequenceItem items[] = {
2353 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2354 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2357 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2358 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2364 SetLastError(STATUS_ACCESS_VIOLATION);
2371 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2372 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2373 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2379 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2380 DWORD bytesNeeded, lenBytes;
2382 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2383 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2385 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2386 bytesNeeded = 1 + lenBytes + blob->cbData;
2389 *pcbEncoded = bytesNeeded;
2394 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2395 pcbEncoded, bytesNeeded)))
2397 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2398 pbEncoded = *(BYTE **)pbEncoded;
2399 *pbEncoded++ = ASN_OCTETSTRING;
2400 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2401 pbEncoded += lenBytes;
2403 memcpy(pbEncoded, blob->pbData, blob->cbData);
2409 SetLastError(STATUS_ACCESS_VIOLATION);
2413 TRACE("returning %d (%08x)\n", ret, GetLastError());
2417 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2418 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2419 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2425 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2426 DWORD bytesNeeded, lenBytes, dataBytes;
2429 /* yep, MS allows cUnusedBits to be >= 8 */
2430 if (!blob->cUnusedBits)
2432 dataBytes = blob->cbData;
2435 else if (blob->cbData * 8 > blob->cUnusedBits)
2437 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2438 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2446 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2447 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2450 *pcbEncoded = bytesNeeded;
2455 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2456 pcbEncoded, bytesNeeded)))
2458 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2459 pbEncoded = *(BYTE **)pbEncoded;
2460 *pbEncoded++ = ASN_BITSTRING;
2461 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2462 pbEncoded += lenBytes;
2463 *pbEncoded++ = unusedBits;
2466 BYTE mask = 0xff << unusedBits;
2470 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2471 pbEncoded += dataBytes - 1;
2473 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2480 SetLastError(STATUS_ACCESS_VIOLATION);
2487 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2488 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2489 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2495 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2496 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2501 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2506 for (i = 0; i < newBlob.cbData; i++)
2507 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2513 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2514 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2515 CryptMemFree(newBlob.pbData);
2519 SetLastError(STATUS_ACCESS_VIOLATION);
2526 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2527 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2528 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2530 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2532 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2533 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2536 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2537 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2538 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2544 DWORD significantBytes, lenBytes;
2545 BYTE padByte = 0, bytesNeeded;
2547 const CRYPT_INTEGER_BLOB *blob =
2548 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2550 significantBytes = blob->cbData;
2551 if (significantBytes)
2553 if (blob->pbData[significantBytes - 1] & 0x80)
2555 /* negative, lop off leading (little-endian) 0xffs */
2556 for (; significantBytes > 0 &&
2557 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2559 if (blob->pbData[significantBytes - 1] < 0x80)
2567 /* positive, lop off leading (little-endian) zeroes */
2568 for (; significantBytes > 0 &&
2569 !blob->pbData[significantBytes - 1]; significantBytes--)
2571 if (significantBytes == 0)
2572 significantBytes = 1;
2573 if (blob->pbData[significantBytes - 1] > 0x7f)
2581 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2583 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2584 bytesNeeded = 1 + lenBytes + significantBytes;
2589 *pcbEncoded = bytesNeeded;
2594 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2595 pcbEncoded, bytesNeeded)))
2597 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2598 pbEncoded = *(BYTE **)pbEncoded;
2599 *pbEncoded++ = ASN_INTEGER;
2602 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2603 pbEncoded += lenBytes;
2604 *pbEncoded++ = padByte;
2608 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2609 pbEncoded += lenBytes;
2611 for (; significantBytes > 0; significantBytes--)
2612 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2618 SetLastError(STATUS_ACCESS_VIOLATION);
2625 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2626 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2627 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2633 DWORD significantBytes, lenBytes;
2636 const CRYPT_INTEGER_BLOB *blob =
2637 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2639 significantBytes = blob->cbData;
2640 if (significantBytes)
2642 /* positive, lop off leading (little-endian) zeroes */
2643 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2646 if (significantBytes == 0)
2647 significantBytes = 1;
2648 if (blob->pbData[significantBytes - 1] > 0x7f)
2652 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2654 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2655 bytesNeeded = 1 + lenBytes + significantBytes;
2660 *pcbEncoded = bytesNeeded;
2665 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2666 pcbEncoded, bytesNeeded)))
2668 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2669 pbEncoded = *(BYTE **)pbEncoded;
2670 *pbEncoded++ = ASN_INTEGER;
2673 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2674 pbEncoded += lenBytes;
2679 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2680 pbEncoded += lenBytes;
2682 for (; significantBytes > 0; significantBytes--)
2683 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2689 SetLastError(STATUS_ACCESS_VIOLATION);
2696 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2697 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2698 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2700 CRYPT_INTEGER_BLOB blob;
2703 /* Encode as an unsigned integer, then change the tag to enumerated */
2704 blob.cbData = sizeof(DWORD);
2705 blob.pbData = (BYTE *)pvStructInfo;
2706 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2707 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2708 if (ret && pbEncoded)
2710 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2711 pbEncoded = *(BYTE **)pbEncoded;
2712 pbEncoded[0] = ASN_ENUMERATED;
2717 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2718 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2719 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2726 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2727 * temporary buffer because the output buffer is not NULL-terminated.
2730 static const DWORD bytesNeeded = sizeof(buf) - 1;
2734 *pcbEncoded = bytesNeeded;
2739 /* Sanity check the year, this is a two-digit year format */
2740 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2742 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2744 SetLastError(CRYPT_E_BAD_ENCODE);
2749 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2750 pbEncoded, pcbEncoded, bytesNeeded)))
2752 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2753 pbEncoded = *(BYTE **)pbEncoded;
2754 buf[0] = ASN_UTCTIME;
2755 buf[1] = bytesNeeded - 2;
2756 snprintf(buf + 2, sizeof(buf) - 2,
2757 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2758 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2759 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2760 sysTime.wMinute, sysTime.wSecond);
2761 memcpy(pbEncoded, buf, bytesNeeded);
2768 SetLastError(STATUS_ACCESS_VIOLATION);
2775 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2776 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2777 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2784 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2785 * temporary buffer because the output buffer is not NULL-terminated.
2788 static const DWORD bytesNeeded = sizeof(buf) - 1;
2792 *pcbEncoded = bytesNeeded;
2797 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2800 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2801 pcbEncoded, bytesNeeded);
2804 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2805 pbEncoded = *(BYTE **)pbEncoded;
2806 buf[0] = ASN_GENERALTIME;
2807 buf[1] = bytesNeeded - 2;
2808 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2809 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2810 sysTime.wMinute, sysTime.wSecond);
2811 memcpy(pbEncoded, buf, bytesNeeded);
2817 SetLastError(STATUS_ACCESS_VIOLATION);
2824 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2825 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2826 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2834 /* Check the year, if it's in the UTCTime range call that encode func */
2835 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2837 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2838 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2839 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2841 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2842 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2847 SetLastError(STATUS_ACCESS_VIOLATION);
2854 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2855 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2856 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2862 DWORD bytesNeeded, dataLen, lenBytes, i;
2863 const CRYPT_SEQUENCE_OF_ANY *seq =
2864 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2866 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2867 dataLen += seq->rgValue[i].cbData;
2868 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2869 bytesNeeded = 1 + lenBytes + dataLen;
2872 *pcbEncoded = bytesNeeded;
2877 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2878 pcbEncoded, bytesNeeded)))
2880 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2881 pbEncoded = *(BYTE **)pbEncoded;
2882 *pbEncoded++ = ASN_SEQUENCEOF;
2883 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2884 pbEncoded += lenBytes;
2885 for (i = 0; i < seq->cValue; i++)
2887 memcpy(pbEncoded, seq->rgValue[i].pbData,
2888 seq->rgValue[i].cbData);
2889 pbEncoded += seq->rgValue[i].cbData;
2896 SetLastError(STATUS_ACCESS_VIOLATION);
2903 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2904 BYTE *pbEncoded, DWORD *pcbEncoded)
2907 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2908 struct AsnConstructedItem constructed = { 0 };
2909 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2910 DWORD cItem = 0, cSwapped = 0;
2912 switch (distPoint->DistPointName.dwDistPointNameChoice)
2914 case CRL_DIST_POINT_NO_NAME:
2917 case CRL_DIST_POINT_FULL_NAME:
2918 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2919 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2920 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2921 constructed.tag = 0;
2922 constructed.pvStructInfo = &swapped[cSwapped];
2923 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2924 items[cItem].pvStructInfo = &constructed;
2925 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2929 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2930 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2936 if (ret && distPoint->ReasonFlags.cbData)
2938 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2939 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2940 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2941 items[cItem].pvStructInfo = &swapped[cSwapped];
2942 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2946 if (ret && distPoint->CRLIssuer.cAltEntry)
2948 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2949 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2950 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2951 items[cItem].pvStructInfo = &swapped[cSwapped];
2952 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2957 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2958 pbEncoded, pcbEncoded);
2962 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2963 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2964 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2970 const CRL_DIST_POINTS_INFO *info =
2971 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2973 if (!info->cDistPoint)
2975 SetLastError(E_INVALIDARG);
2980 DWORD bytesNeeded, dataLen, lenBytes, i;
2983 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2987 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2991 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2993 /* Have to propagate index of failing character */
2999 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3000 bytesNeeded = 1 + lenBytes + dataLen;
3003 *pcbEncoded = bytesNeeded;
3008 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3009 pbEncoded, pcbEncoded, bytesNeeded)))
3011 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3012 pbEncoded = *(BYTE **)pbEncoded;
3013 *pbEncoded++ = ASN_SEQUENCEOF;
3014 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3015 pbEncoded += lenBytes;
3016 for (i = 0; ret && i < info->cDistPoint; i++)
3018 DWORD len = dataLen;
3020 ret = CRYPT_AsnEncodeDistPoint(
3021 &info->rgDistPoint[i], pbEncoded, &len);
3035 SetLastError(STATUS_ACCESS_VIOLATION);
3042 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3043 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3044 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3050 const CERT_ENHKEY_USAGE *usage =
3051 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3052 DWORD bytesNeeded = 0, lenBytes, size, i;
3055 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3057 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3058 usage->rgpszUsageIdentifier[i],
3059 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3061 bytesNeeded += size;
3063 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3064 bytesNeeded += 1 + lenBytes;
3068 *pcbEncoded = bytesNeeded;
3071 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3072 pbEncoded, pcbEncoded, bytesNeeded)))
3074 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3075 pbEncoded = *(BYTE **)pbEncoded;
3076 *pbEncoded++ = ASN_SEQUENCEOF;
3077 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3079 pbEncoded += lenBytes;
3080 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3083 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3084 usage->rgpszUsageIdentifier[i],
3085 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3090 bytesNeeded -= size;
3099 SetLastError(STATUS_ACCESS_VIOLATION);
3106 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3107 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3108 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3114 const CRL_ISSUING_DIST_POINT *point =
3115 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3116 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3117 struct AsnConstructedItem constructed = { 0 };
3118 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3119 DWORD cItem = 0, cSwapped = 0;
3122 switch (point->DistPointName.dwDistPointNameChoice)
3124 case CRL_DIST_POINT_NO_NAME:
3127 case CRL_DIST_POINT_FULL_NAME:
3128 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3129 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3130 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3131 constructed.tag = 0;
3132 constructed.pvStructInfo = &swapped[cSwapped];
3133 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3134 items[cItem].pvStructInfo = &constructed;
3135 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3140 SetLastError(E_INVALIDARG);
3143 if (ret && point->fOnlyContainsUserCerts)
3145 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3146 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3147 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3148 items[cItem].pvStructInfo = &swapped[cSwapped];
3149 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3153 if (ret && point->fOnlyContainsCACerts)
3155 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3156 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3157 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3158 items[cItem].pvStructInfo = &swapped[cSwapped];
3159 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3163 if (ret && point->OnlySomeReasonFlags.cbData)
3165 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3166 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3167 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3168 items[cItem].pvStructInfo = &swapped[cSwapped];
3169 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3173 if (ret && point->fIndirectCRL)
3175 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3176 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3177 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3178 items[cItem].pvStructInfo = &swapped[cSwapped];
3179 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3184 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3185 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3189 SetLastError(STATUS_ACCESS_VIOLATION);
3196 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3197 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3198 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3201 const CERT_GENERAL_SUBTREE *subtree =
3202 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3203 struct AsnEncodeSequenceItem items[3] = {
3204 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3207 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3208 DWORD cItem = 1, cSwapped = 0;
3210 if (subtree->dwMinimum)
3212 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3213 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3214 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3215 items[cItem].pvStructInfo = &swapped[cSwapped];
3216 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3220 if (subtree->fMaximum)
3222 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3223 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3224 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3225 items[cItem].pvStructInfo = &swapped[cSwapped];
3226 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3230 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3231 pEncodePara, pbEncoded, pcbEncoded);
3235 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3236 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3237 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3240 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3242 TRACE("%p\n", pvStructInfo);
3246 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3247 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3248 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3249 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3250 DWORD i, cItem = 0, cSwapped = 0;
3253 if (constraints->cPermittedSubtree)
3255 permitted.rgBlob = CryptMemAlloc(
3256 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3257 if (permitted.rgBlob)
3259 permitted.cBlob = constraints->cPermittedSubtree;
3260 memset(permitted.rgBlob, 0,
3261 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3262 for (i = 0; ret && i < permitted.cBlob; i++)
3263 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3264 NULL, &constraints->rgPermittedSubtree[i],
3265 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3266 (BYTE *)&permitted.rgBlob[i].pbData,
3267 &permitted.rgBlob[i].cbData);
3270 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3271 swapped[cSwapped].pvStructInfo = &permitted;
3272 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3273 items[cItem].pvStructInfo = &swapped[cSwapped];
3274 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3282 if (constraints->cExcludedSubtree)
3284 excluded.rgBlob = CryptMemAlloc(
3285 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3286 if (excluded.rgBlob)
3288 excluded.cBlob = constraints->cExcludedSubtree;
3289 memset(excluded.rgBlob, 0,
3290 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3291 for (i = 0; ret && i < excluded.cBlob; i++)
3292 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3293 NULL, &constraints->rgExcludedSubtree[i],
3294 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3295 (BYTE *)&excluded.rgBlob[i].pbData,
3296 &excluded.rgBlob[i].cbData);
3299 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3300 swapped[cSwapped].pvStructInfo = &excluded;
3301 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3302 items[cItem].pvStructInfo = &swapped[cSwapped];
3303 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3312 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3313 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3314 for (i = 0; i < permitted.cBlob; i++)
3315 LocalFree(permitted.rgBlob[i].pbData);
3316 for (i = 0; i < excluded.cBlob; i++)
3317 LocalFree(excluded.rgBlob[i].pbData);
3321 SetLastError(STATUS_ACCESS_VIOLATION);
3324 CryptMemFree(permitted.rgBlob);
3325 CryptMemFree(excluded.rgBlob);
3326 TRACE("returning %d\n", ret);
3330 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3331 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3332 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3336 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3337 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3338 struct AsnEncodeSequenceItem items[] = {
3339 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3340 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3343 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3344 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3349 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3350 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3351 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3355 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3357 SetLastError(E_INVALIDARG);
3363 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3365 if (!info->Issuer.cbData)
3366 SetLastError(E_INVALIDARG);
3369 struct AsnEncodeSequenceItem items[7] = {
3370 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3371 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3372 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3375 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3376 DWORD cItem = 3, cSwapped = 0;
3378 if (info->AuthAttrs.cAttr)
3380 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3381 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3382 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3383 items[cItem].pvStructInfo = &swapped[cSwapped];
3384 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3388 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3389 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3391 items[cItem].pvStructInfo = &info->EncryptedHash;
3392 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3394 if (info->UnauthAttrs.cAttr)
3396 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3397 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3398 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3399 items[cItem].pvStructInfo = &swapped[cSwapped];
3400 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3404 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3405 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3410 SetLastError(STATUS_ACCESS_VIOLATION);
3416 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3419 struct AsnEncodeSequenceItem items[7] = {
3420 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3422 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3423 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3424 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3425 DWORD cItem = 1, cSwapped = 0;
3428 if (signedInfo->cSignerInfo)
3430 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3431 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3432 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3433 digestAlgorithmsSet.itemOffset =
3434 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3435 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3436 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3437 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3440 items[cItem].pvStructInfo = &signedInfo->content;
3441 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3443 if (signedInfo->cCertEncoded)
3445 certSet.cItems = signedInfo->cCertEncoded;
3446 certSet.items = signedInfo->rgCertEncoded;
3447 certSet.itemSize = sizeof(CERT_BLOB);
3448 certSet.itemOffset = 0;
3449 certSet.encode = CRYPT_CopyEncodedBlob;
3450 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3451 swapped[cSwapped].pvStructInfo = &certSet;
3452 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3453 items[cItem].pvStructInfo = &swapped[cSwapped];
3454 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3458 if (signedInfo->cCrlEncoded)
3460 crlSet.cItems = signedInfo->cCrlEncoded;
3461 crlSet.items = signedInfo->rgCrlEncoded;
3462 crlSet.itemSize = sizeof(CRL_BLOB);
3463 crlSet.itemOffset = 0;
3464 crlSet.encode = CRYPT_CopyEncodedBlob;
3465 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3466 swapped[cSwapped].pvStructInfo = &crlSet;
3467 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3468 items[cItem].pvStructInfo = &swapped[cSwapped];
3469 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3473 if (ret && signedInfo->cSignerInfo)
3475 signerSet.cItems = signedInfo->cSignerInfo;
3476 signerSet.items = signedInfo->rgSignerInfo;
3477 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3478 signerSet.itemOffset = 0;
3479 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3480 items[cItem].pvStructInfo = &signerSet;
3481 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3485 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3486 items, cItem, 0, NULL, pvData, pcbData);
3491 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3492 LPCSTR lpszStructType)
3494 CryptEncodeObjectExFunc encodeFunc = NULL;
3496 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3497 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3499 SetLastError(ERROR_FILE_NOT_FOUND);
3503 if (!HIWORD(lpszStructType))
3505 switch (LOWORD(lpszStructType))
3507 case LOWORD(X509_CERT):
3508 encodeFunc = CRYPT_AsnEncodeCert;
3510 case LOWORD(X509_CERT_TO_BE_SIGNED):
3511 encodeFunc = CRYPT_AsnEncodeCertInfo;
3513 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3514 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3516 case LOWORD(X509_EXTENSIONS):
3517 encodeFunc = CRYPT_AsnEncodeExtensions;
3519 case LOWORD(X509_NAME_VALUE):
3520 encodeFunc = CRYPT_AsnEncodeNameValue;
3522 case LOWORD(X509_NAME):
3523 encodeFunc = CRYPT_AsnEncodeName;
3525 case LOWORD(X509_PUBLIC_KEY_INFO):
3526 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3528 case LOWORD(X509_AUTHORITY_KEY_ID):
3529 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3531 case LOWORD(X509_ALTERNATE_NAME):
3532 encodeFunc = CRYPT_AsnEncodeAltName;
3534 case LOWORD(X509_BASIC_CONSTRAINTS):
3535 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3537 case LOWORD(X509_BASIC_CONSTRAINTS2):
3538 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3540 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3541 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3543 case LOWORD(X509_UNICODE_NAME):
3544 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3546 case LOWORD(PKCS_CONTENT_INFO):
3547 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3549 case LOWORD(PKCS_ATTRIBUTE):
3550 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3552 case LOWORD(X509_UNICODE_NAME_VALUE):
3553 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3555 case LOWORD(X509_OCTET_STRING):
3556 encodeFunc = CRYPT_AsnEncodeOctets;
3558 case LOWORD(X509_BITS):
3559 case LOWORD(X509_KEY_USAGE):
3560 encodeFunc = CRYPT_AsnEncodeBits;
3562 case LOWORD(X509_INTEGER):
3563 encodeFunc = CRYPT_AsnEncodeInt;
3565 case LOWORD(X509_MULTI_BYTE_INTEGER):
3566 encodeFunc = CRYPT_AsnEncodeInteger;
3568 case LOWORD(X509_MULTI_BYTE_UINT):
3569 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3571 case LOWORD(X509_ENUMERATED):
3572 encodeFunc = CRYPT_AsnEncodeEnumerated;
3574 case LOWORD(X509_CHOICE_OF_TIME):
3575 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3577 case LOWORD(X509_AUTHORITY_KEY_ID2):
3578 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3580 case LOWORD(X509_SEQUENCE_OF_ANY):
3581 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3583 case LOWORD(PKCS_UTC_TIME):
3584 encodeFunc = CRYPT_AsnEncodeUtcTime;
3586 case LOWORD(X509_CRL_DIST_POINTS):
3587 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3589 case LOWORD(X509_ENHANCED_KEY_USAGE):
3590 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3592 case LOWORD(PKCS_ATTRIBUTES):
3593 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3595 case LOWORD(X509_ISSUING_DIST_POINT):
3596 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3598 case LOWORD(X509_NAME_CONSTRAINTS):
3599 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3601 case LOWORD(PKCS7_SIGNER_INFO):
3602 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3606 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3607 encodeFunc = CRYPT_AsnEncodeExtensions;
3608 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3609 encodeFunc = CRYPT_AsnEncodeUtcTime;
3610 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3611 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3612 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3613 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3614 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3615 encodeFunc = CRYPT_AsnEncodeEnumerated;
3616 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3617 encodeFunc = CRYPT_AsnEncodeBits;
3618 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3619 encodeFunc = CRYPT_AsnEncodeOctets;
3620 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3621 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3622 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3623 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3624 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3625 encodeFunc = CRYPT_AsnEncodeAltName;
3626 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3627 encodeFunc = CRYPT_AsnEncodeAltName;
3628 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3629 encodeFunc = CRYPT_AsnEncodeAltName;
3630 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3631 encodeFunc = CRYPT_AsnEncodeAltName;
3632 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3633 encodeFunc = CRYPT_AsnEncodeAltName;
3634 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3635 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3636 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3637 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3638 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3639 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3640 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3641 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3645 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3646 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3648 static HCRYPTOIDFUNCSET set = NULL;
3649 CryptEncodeObjectFunc encodeFunc = NULL;
3652 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3653 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3654 (void **)&encodeFunc, hFunc);
3658 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3659 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3661 static HCRYPTOIDFUNCSET set = NULL;
3662 CryptEncodeObjectExFunc encodeFunc = NULL;
3665 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3666 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3667 (void **)&encodeFunc, hFunc);
3671 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3672 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3675 HCRYPTOIDFUNCADDR hFunc = NULL;
3676 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3677 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3679 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3680 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3683 if (!pbEncoded && !pcbEncoded)
3685 SetLastError(ERROR_INVALID_PARAMETER);
3689 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3692 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3693 debugstr_a(lpszStructType));
3694 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3695 lpszStructType, &hFunc);
3696 if (!pCryptEncodeObject)
3697 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3698 lpszStructType, &hFunc);
3700 if (pCryptEncodeObject)
3701 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3702 pvStructInfo, pbEncoded, pcbEncoded);
3703 else if (pCryptEncodeObjectEx)
3704 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3705 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3707 CryptFreeOIDFunctionAddress(hFunc, 0);
3708 TRACE_(crypt)("returning %d\n", ret);
3712 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3713 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3714 void *pvEncoded, DWORD *pcbEncoded)
3717 HCRYPTOIDFUNCADDR hFunc = NULL;
3718 CryptEncodeObjectExFunc encodeFunc = NULL;
3720 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3721 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3722 pvEncoded, pcbEncoded);
3724 if (!pvEncoded && !pcbEncoded)
3726 SetLastError(ERROR_INVALID_PARAMETER);
3730 SetLastError(NOERROR);
3731 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3732 *(BYTE **)pvEncoded = NULL;
3733 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3736 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3737 debugstr_a(lpszStructType));
3738 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3742 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3743 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3746 CryptEncodeObjectFunc pCryptEncodeObject =
3747 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3749 if (pCryptEncodeObject)
3751 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3753 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3754 pvStructInfo, NULL, pcbEncoded);
3755 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3756 pvEncoded, pcbEncoded, *pcbEncoded)))
3757 ret = pCryptEncodeObject(dwCertEncodingType,
3758 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3762 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3763 pvStructInfo, pvEncoded, pcbEncoded);
3767 CryptFreeOIDFunctionAddress(hFunc, 0);
3768 TRACE_(crypt)("returning %d\n", ret);
3772 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3773 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3775 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3776 NULL, 0, NULL, pInfo, pcbInfo);
3779 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3780 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3781 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3785 static CHAR oid[] = szOID_RSA_RSA;
3787 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3788 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3789 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3791 if (!pszPublicKeyObjId)
3792 pszPublicKeyObjId = oid;
3793 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3797 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3800 LPBYTE pubKey = CryptMemAlloc(keySize);
3804 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3808 DWORD encodedLen = 0;
3810 ret = CryptEncodeObject(dwCertEncodingType,
3811 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3814 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3815 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3818 *pcbInfo = sizeNeeded;
3819 else if (*pcbInfo < sizeNeeded)
3821 SetLastError(ERROR_MORE_DATA);
3822 *pcbInfo = sizeNeeded;
3827 pInfo->Algorithm.pszObjId = (char *)pInfo +
3828 sizeof(CERT_PUBLIC_KEY_INFO);
3829 lstrcpyA(pInfo->Algorithm.pszObjId,
3831 pInfo->Algorithm.Parameters.cbData = 0;
3832 pInfo->Algorithm.Parameters.pbData = NULL;
3833 pInfo->PublicKey.pbData =
3834 (BYTE *)pInfo->Algorithm.pszObjId
3835 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3836 pInfo->PublicKey.cbData = encodedLen;
3837 pInfo->PublicKey.cUnusedBits = 0;
3838 ret = CryptEncodeObject(dwCertEncodingType,
3839 RSA_CSP_PUBLICKEYBLOB, pubKey,
3840 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3844 CryptMemFree(pubKey);
3849 CryptDestroyKey(key);
3854 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3855 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3856 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3858 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3859 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3860 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3862 static HCRYPTOIDFUNCSET set = NULL;
3864 ExportPublicKeyInfoExFunc exportFunc = NULL;
3865 HCRYPTOIDFUNCADDR hFunc = NULL;
3867 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3868 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3869 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3873 SetLastError(ERROR_INVALID_PARAMETER);
3877 if (pszPublicKeyObjId)
3880 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3882 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3883 0, (void **)&exportFunc, &hFunc);
3886 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3887 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3888 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3890 CryptFreeOIDFunctionAddress(hFunc, 0);
3894 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3895 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3897 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3901 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3902 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3903 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3906 DWORD pubKeySize = 0;
3908 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3909 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3911 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3912 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3915 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3919 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3920 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3923 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3925 CryptMemFree(pubKey);
3933 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3934 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3935 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3937 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3938 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3939 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3941 static HCRYPTOIDFUNCSET set = NULL;
3943 ImportPublicKeyInfoExFunc importFunc = NULL;
3944 HCRYPTOIDFUNCADDR hFunc = NULL;
3946 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3947 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3950 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3951 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3952 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3954 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3955 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3958 CryptFreeOIDFunctionAddress(hFunc, 0);