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 + 1, 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;
1231 for (i = 0; i < setOf.cBlob; i++)
1232 bytesNeeded += setOf.rgBlob[i].cbData;
1233 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1234 bytesNeeded += 1 + lenBytes;
1236 *pcbEncoded = bytesNeeded;
1237 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1238 pbEncoded, pcbEncoded, bytesNeeded)))
1240 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1241 pbEncoded = *(BYTE **)pbEncoded;
1242 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1244 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1245 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1246 pbEncoded += lenBytes;
1247 for (i = 0; i < setOf.cBlob; i++)
1249 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1250 setOf.rgBlob[i].cbData);
1251 pbEncoded += setOf.rgBlob[i].cbData;
1255 for (i = 0; i < setOf.cBlob; i++)
1256 CryptMemFree(setOf.rgBlob[i].pbData);
1257 CryptMemFree(setOf.rgBlob);
1261 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1262 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1266 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1275 setOf.cBlob = rdn->cRDNAttr;
1276 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1277 sizeof(CRYPT_DER_BLOB));
1281 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1283 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1285 setOf.rgBlob[i].cbData = 0;
1286 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1287 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1290 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1291 if (!setOf.rgBlob[i].pbData)
1294 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1295 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1296 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1300 /* Have to propagate index of failing character */
1301 *pcbEncoded = setOf.rgBlob[i].cbData;
1305 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1306 pbEncoded, pcbEncoded);
1307 for (i = 0; i < setOf.cBlob; i++)
1308 CryptMemFree(setOf.rgBlob[i].pbData);
1312 SetLastError(STATUS_ACCESS_VIOLATION);
1316 CryptMemFree(setOf.rgBlob);
1320 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1321 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1322 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1324 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1325 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1326 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1329 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1332 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1333 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1334 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1336 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1337 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1341 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1349 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1350 DWORD bytesNeeded = 0, lenBytes, size, i;
1352 TRACE("encoding name with %d RDNs\n", info->cRDN);
1354 for (i = 0; ret && i < info->cRDN; i++)
1356 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1357 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1359 bytesNeeded += size;
1363 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1364 bytesNeeded += 1 + lenBytes;
1368 *pcbEncoded = bytesNeeded;
1371 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1372 pbEncoded, pcbEncoded, bytesNeeded)))
1374 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1375 pbEncoded = *(BYTE **)pbEncoded;
1376 *pbEncoded++ = ASN_SEQUENCEOF;
1377 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1379 pbEncoded += lenBytes;
1380 for (i = 0; ret && i < info->cRDN; i++)
1383 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1384 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1389 bytesNeeded -= size;
1400 SetLastError(STATUS_ACCESS_VIOLATION);
1407 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1408 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1409 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1415 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1417 if (!attr->pszObjId)
1418 SetLastError(E_INVALIDARG);
1421 struct AsnEncodeSequenceItem items[2] = {
1422 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1423 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1426 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1427 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1433 SetLastError(STATUS_ACCESS_VIOLATION);
1439 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1440 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1441 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1447 const CRYPT_ATTRIBUTES *attributes =
1448 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1449 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1450 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1452 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1453 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1457 SetLastError(STATUS_ACCESS_VIOLATION);
1463 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1464 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1465 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1466 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1469 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1470 struct AsnEncodeSequenceItem items[2] = {
1471 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1474 struct AsnConstructedItem constructed = { 0 };
1477 if (info->Content.cbData)
1479 constructed.tag = 0;
1480 constructed.pvStructInfo = &info->Content;
1481 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1482 items[cItem].pvStructInfo = &constructed;
1483 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1486 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1487 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1490 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1491 void *pvData, DWORD *pcbData)
1493 struct AsnEncodeSequenceItem items[] = {
1494 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1495 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1497 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1498 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1501 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1502 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1505 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1506 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1507 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1513 const CRYPT_CONTENT_INFO *info =
1514 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1516 if (!info->pszObjId)
1517 SetLastError(E_INVALIDARG);
1519 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1520 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1525 SetLastError(STATUS_ACCESS_VIOLATION);
1531 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1532 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1536 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1537 DWORD bytesNeeded, lenBytes, encodedLen;
1539 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1541 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1542 bytesNeeded = 1 + lenBytes + encodedLen;
1544 *pcbEncoded = bytesNeeded;
1547 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1548 pbEncoded, pcbEncoded, bytesNeeded)))
1552 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1553 pbEncoded = *(BYTE **)pbEncoded;
1555 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1556 pbEncoded += lenBytes;
1557 for (i = 0; i < encodedLen; i++)
1558 *pbEncoded++ = (BYTE)str[i];
1564 static void CRYPT_FreeSpace(PCRYPT_ENCODE_PARA pEncodePara, LPVOID pv)
1566 if (pEncodePara && pEncodePara->pfnFree)
1567 pEncodePara->pfnFree(pv);
1572 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1573 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1577 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1578 DWORD bytesNeeded, lenBytes, encodedLen;
1580 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1582 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1583 bytesNeeded = 1 + lenBytes + encodedLen;
1585 *pcbEncoded = bytesNeeded;
1588 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1589 pbEncoded, pcbEncoded, bytesNeeded)))
1594 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1595 ptr = *(BYTE **)pbEncoded;
1598 *ptr++ = ASN_NUMERICSTRING;
1599 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1601 for (i = 0; ret && i < encodedLen; i++)
1603 if (isdigitW(str[i]))
1604 *ptr++ = (BYTE)str[i];
1608 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1612 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1613 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
1619 static inline int isprintableW(WCHAR wc)
1621 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1622 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1623 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1626 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1627 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1631 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1632 DWORD bytesNeeded, lenBytes, encodedLen;
1634 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1636 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1637 bytesNeeded = 1 + lenBytes + encodedLen;
1639 *pcbEncoded = bytesNeeded;
1642 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1643 pbEncoded, pcbEncoded, bytesNeeded)))
1648 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1649 ptr = *(BYTE **)pbEncoded;
1652 *ptr++ = ASN_PRINTABLESTRING;
1653 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1655 for (i = 0; ret && i < encodedLen; i++)
1657 if (isprintableW(str[i]))
1658 *ptr++ = (BYTE)str[i];
1662 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1666 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1667 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
1673 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1674 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1678 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1679 DWORD bytesNeeded, lenBytes, encodedLen;
1681 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1683 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1684 bytesNeeded = 1 + lenBytes + encodedLen;
1686 *pcbEncoded = bytesNeeded;
1689 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1690 pbEncoded, pcbEncoded, bytesNeeded)))
1695 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1696 ptr = *(BYTE **)pbEncoded;
1699 *ptr++ = ASN_IA5STRING;
1700 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
1702 for (i = 0; ret && i < encodedLen; i++)
1705 *ptr++ = (BYTE)str[i];
1709 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1713 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1714 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
1720 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1721 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1725 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1726 DWORD bytesNeeded, lenBytes, strLen;
1728 /* FIXME: doesn't handle composite characters */
1729 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1731 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1732 bytesNeeded = 1 + lenBytes + strLen * 4;
1734 *pcbEncoded = bytesNeeded;
1737 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1738 pbEncoded, pcbEncoded, bytesNeeded)))
1742 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1743 pbEncoded = *(BYTE **)pbEncoded;
1744 *pbEncoded++ = ASN_UNIVERSALSTRING;
1745 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1746 pbEncoded += lenBytes;
1747 for (i = 0; i < strLen; i++)
1751 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1752 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1759 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1760 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1761 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1767 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1769 switch (value->dwValueType)
1771 case CERT_RDN_ANY_TYPE:
1772 case CERT_RDN_ENCODED_BLOB:
1773 case CERT_RDN_OCTET_STRING:
1774 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1776 case CERT_RDN_NUMERIC_STRING:
1777 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1778 pbEncoded, pcbEncoded);
1780 case CERT_RDN_PRINTABLE_STRING:
1781 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1782 pbEncoded, pcbEncoded);
1784 case CERT_RDN_TELETEX_STRING:
1785 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1786 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1788 case CERT_RDN_VIDEOTEX_STRING:
1789 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1790 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1792 case CERT_RDN_IA5_STRING:
1793 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1794 pbEncoded, pcbEncoded);
1796 case CERT_RDN_GRAPHIC_STRING:
1797 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1798 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1800 case CERT_RDN_VISIBLE_STRING:
1801 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1802 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1804 case CERT_RDN_GENERAL_STRING:
1805 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1806 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1808 case CERT_RDN_UNIVERSAL_STRING:
1809 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1810 pbEncoded, pcbEncoded);
1812 case CERT_RDN_BMP_STRING:
1813 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1814 pbEncoded, pcbEncoded);
1816 case CERT_RDN_UTF8_STRING:
1817 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1818 pbEncoded, pcbEncoded);
1821 SetLastError(CRYPT_E_ASN1_CHOICE);
1826 SetLastError(STATUS_ACCESS_VIOLATION);
1832 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1833 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1834 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1840 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1841 DWORD bytesNeeded = 0, lenBytes, size, i;
1843 TRACE("encoding name with %d RDNs\n", info->cRDN);
1845 for (i = 0; ret && i < info->cRDN; i++)
1847 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1848 CRYPT_AsnEncodeNameValue, NULL, &size);
1850 bytesNeeded += size;
1852 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1853 bytesNeeded += 1 + lenBytes;
1857 *pcbEncoded = bytesNeeded;
1860 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1861 pbEncoded, pcbEncoded, bytesNeeded)))
1863 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1864 pbEncoded = *(BYTE **)pbEncoded;
1865 *pbEncoded++ = ASN_SEQUENCEOF;
1866 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1868 pbEncoded += lenBytes;
1869 for (i = 0; ret && i < info->cRDN; i++)
1872 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1873 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1878 bytesNeeded -= size;
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1894 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1895 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1896 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1898 BOOL val = *(const BOOL *)pvStructInfo, ret;
1907 else if (*pcbEncoded < 3)
1910 SetLastError(ERROR_MORE_DATA);
1916 *pbEncoded++ = ASN_BOOL;
1918 *pbEncoded++ = val ? 0xff : 0;
1921 TRACE("returning %d (%08x)\n", ret, GetLastError());
1925 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1926 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1927 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1929 const CERT_ALT_NAME_ENTRY *entry =
1930 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1936 switch (entry->dwAltNameChoice)
1938 case CERT_ALT_NAME_RFC822_NAME:
1939 case CERT_ALT_NAME_DNS_NAME:
1940 case CERT_ALT_NAME_URL:
1941 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1942 if (entry->u.pwszURL)
1946 /* Not + 1: don't encode the NULL-terminator */
1947 dataLen = lstrlenW(entry->u.pwszURL);
1948 for (i = 0; ret && i < dataLen; i++)
1950 if (entry->u.pwszURL[i] > 0x7f)
1952 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1961 case CERT_ALT_NAME_DIRECTORY_NAME:
1962 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1963 dataLen = entry->u.DirectoryName.cbData;
1965 case CERT_ALT_NAME_IP_ADDRESS:
1966 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1967 dataLen = entry->u.IPAddress.cbData;
1969 case CERT_ALT_NAME_REGISTERED_ID:
1971 struct AsnEncodeTagSwappedItem swapped =
1972 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1973 CRYPT_AsnEncodeOid };
1975 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1978 case CERT_ALT_NAME_OTHER_NAME:
1979 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1982 SetLastError(E_INVALIDARG);
1987 DWORD bytesNeeded, lenBytes;
1989 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1990 bytesNeeded = 1 + dataLen + lenBytes;
1992 *pcbEncoded = bytesNeeded;
1993 else if (*pcbEncoded < bytesNeeded)
1995 SetLastError(ERROR_MORE_DATA);
1996 *pcbEncoded = bytesNeeded;
2002 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2003 pbEncoded += lenBytes;
2004 switch (entry->dwAltNameChoice)
2006 case CERT_ALT_NAME_RFC822_NAME:
2007 case CERT_ALT_NAME_DNS_NAME:
2008 case CERT_ALT_NAME_URL:
2012 for (i = 0; i < dataLen; i++)
2013 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2016 case CERT_ALT_NAME_DIRECTORY_NAME:
2017 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2019 case CERT_ALT_NAME_IP_ADDRESS:
2020 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2024 *pcbEncoded = bytesNeeded;
2027 TRACE("returning %d (%08x)\n", ret, GetLastError());
2031 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2032 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2033 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2039 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2040 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2045 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2050 for (i = 0; i < newBlob.cbData; i++)
2051 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2057 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2058 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2059 CryptMemFree(newBlob.pbData);
2063 SetLastError(STATUS_ACCESS_VIOLATION);
2070 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2071 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2072 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2078 const CERT_AUTHORITY_KEY_ID_INFO *info =
2079 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2080 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2081 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2082 struct AsnConstructedItem constructed = { 0 };
2083 DWORD cItem = 0, cSwapped = 0;
2085 if (info->KeyId.cbData)
2087 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2088 swapped[cSwapped].pvStructInfo = &info->KeyId;
2089 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2090 items[cItem].pvStructInfo = &swapped[cSwapped];
2091 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2095 if (info->CertIssuer.cbData)
2097 constructed.tag = 1;
2098 constructed.pvStructInfo = &info->CertIssuer;
2099 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2100 items[cItem].pvStructInfo = &constructed;
2101 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2104 if (info->CertSerialNumber.cbData)
2106 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2107 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2108 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2109 items[cItem].pvStructInfo = &swapped[cSwapped];
2110 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2114 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2115 pEncodePara, pbEncoded, pcbEncoded);
2119 SetLastError(STATUS_ACCESS_VIOLATION);
2126 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2127 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2128 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2134 const CERT_ALT_NAME_INFO *info =
2135 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2136 DWORD bytesNeeded, dataLen, lenBytes, i;
2139 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2140 * can't encode an erroneous entry index if it's bigger than this.
2142 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2146 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2147 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2150 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2152 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2153 * the bad character, now set the index of the bad
2156 *pcbEncoded = (BYTE)i <<
2157 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2162 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2163 bytesNeeded = 1 + lenBytes + dataLen;
2166 *pcbEncoded = bytesNeeded;
2171 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2172 pbEncoded, pcbEncoded, bytesNeeded)))
2174 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2175 pbEncoded = *(BYTE **)pbEncoded;
2176 *pbEncoded++ = ASN_SEQUENCEOF;
2177 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2178 pbEncoded += lenBytes;
2179 for (i = 0; ret && i < info->cAltEntry; i++)
2181 DWORD len = dataLen;
2183 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2184 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2197 SetLastError(STATUS_ACCESS_VIOLATION);
2204 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2205 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2206 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2212 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2213 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2214 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2215 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2216 DWORD cItem = 0, cSwapped = 0;
2218 if (info->KeyId.cbData)
2220 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2221 swapped[cSwapped].pvStructInfo = &info->KeyId;
2222 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2223 items[cItem].pvStructInfo = &swapped[cSwapped];
2224 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2228 if (info->AuthorityCertIssuer.cAltEntry)
2230 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2231 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2232 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2233 items[cItem].pvStructInfo = &swapped[cSwapped];
2234 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2238 if (info->AuthorityCertSerialNumber.cbData)
2240 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2241 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2242 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2243 items[cItem].pvStructInfo = &swapped[cSwapped];
2244 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2248 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2249 pEncodePara, pbEncoded, pcbEncoded);
2253 SetLastError(STATUS_ACCESS_VIOLATION);
2260 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2261 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2262 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2268 const CERT_BASIC_CONSTRAINTS_INFO *info =
2269 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2270 struct AsnEncodeSequenceItem items[3] = {
2271 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2276 if (info->fPathLenConstraint)
2278 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2279 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2282 if (info->cSubtreesConstraint)
2284 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2285 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2288 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2289 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2293 SetLastError(STATUS_ACCESS_VIOLATION);
2300 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2301 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2302 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2308 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2309 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2310 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2315 items[cItem].pvStructInfo = &info->fCA;
2316 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2319 if (info->fPathLenConstraint)
2321 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2322 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2325 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2326 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2330 SetLastError(STATUS_ACCESS_VIOLATION);
2337 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2338 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2339 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2345 const BLOBHEADER *hdr =
2346 (const BLOBHEADER *)pvStructInfo;
2348 if (hdr->bType != PUBLICKEYBLOB)
2350 SetLastError(E_INVALIDARG);
2355 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2356 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2357 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2358 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2359 struct AsnEncodeSequenceItem items[] = {
2360 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2361 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2364 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2365 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2371 SetLastError(STATUS_ACCESS_VIOLATION);
2378 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2379 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2380 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2386 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2387 DWORD bytesNeeded, lenBytes;
2389 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2390 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2392 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2393 bytesNeeded = 1 + lenBytes + blob->cbData;
2396 *pcbEncoded = bytesNeeded;
2401 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2402 pcbEncoded, bytesNeeded)))
2404 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2405 pbEncoded = *(BYTE **)pbEncoded;
2406 *pbEncoded++ = ASN_OCTETSTRING;
2407 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2408 pbEncoded += lenBytes;
2410 memcpy(pbEncoded, blob->pbData, blob->cbData);
2416 SetLastError(STATUS_ACCESS_VIOLATION);
2420 TRACE("returning %d (%08x)\n", ret, GetLastError());
2424 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2425 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2426 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2432 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2433 DWORD bytesNeeded, lenBytes, dataBytes;
2436 /* yep, MS allows cUnusedBits to be >= 8 */
2437 if (!blob->cUnusedBits)
2439 dataBytes = blob->cbData;
2442 else if (blob->cbData * 8 > blob->cUnusedBits)
2444 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2445 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2453 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2454 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2457 *pcbEncoded = bytesNeeded;
2462 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2463 pcbEncoded, bytesNeeded)))
2465 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2466 pbEncoded = *(BYTE **)pbEncoded;
2467 *pbEncoded++ = ASN_BITSTRING;
2468 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2469 pbEncoded += lenBytes;
2470 *pbEncoded++ = unusedBits;
2473 BYTE mask = 0xff << unusedBits;
2477 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2478 pbEncoded += dataBytes - 1;
2480 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2487 SetLastError(STATUS_ACCESS_VIOLATION);
2494 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2495 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2496 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2502 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2503 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2508 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2513 for (i = 0; i < newBlob.cbData; i++)
2514 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2520 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2521 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2522 CryptMemFree(newBlob.pbData);
2526 SetLastError(STATUS_ACCESS_VIOLATION);
2533 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2534 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2535 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2537 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2539 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2540 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2543 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2544 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2545 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2551 DWORD significantBytes, lenBytes, bytesNeeded;
2554 const CRYPT_INTEGER_BLOB *blob =
2555 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2557 significantBytes = blob->cbData;
2558 if (significantBytes)
2560 if (blob->pbData[significantBytes - 1] & 0x80)
2562 /* negative, lop off leading (little-endian) 0xffs */
2563 for (; significantBytes > 0 &&
2564 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2566 if (blob->pbData[significantBytes - 1] < 0x80)
2574 /* positive, lop off leading (little-endian) zeroes */
2575 for (; significantBytes > 0 &&
2576 !blob->pbData[significantBytes - 1]; significantBytes--)
2578 if (significantBytes == 0)
2579 significantBytes = 1;
2580 if (blob->pbData[significantBytes - 1] > 0x7f)
2588 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2590 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2591 bytesNeeded = 1 + lenBytes + significantBytes;
2596 *pcbEncoded = bytesNeeded;
2601 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2602 pcbEncoded, bytesNeeded)))
2604 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2605 pbEncoded = *(BYTE **)pbEncoded;
2606 *pbEncoded++ = ASN_INTEGER;
2609 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2610 pbEncoded += lenBytes;
2611 *pbEncoded++ = padByte;
2615 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2616 pbEncoded += lenBytes;
2618 for (; significantBytes > 0; significantBytes--)
2619 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2625 SetLastError(STATUS_ACCESS_VIOLATION);
2632 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2633 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2634 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2640 DWORD significantBytes, lenBytes, bytesNeeded;
2642 const CRYPT_INTEGER_BLOB *blob =
2643 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2645 significantBytes = blob->cbData;
2646 if (significantBytes)
2648 /* positive, lop off leading (little-endian) zeroes */
2649 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2652 if (significantBytes == 0)
2653 significantBytes = 1;
2654 if (blob->pbData[significantBytes - 1] > 0x7f)
2658 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2660 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2661 bytesNeeded = 1 + lenBytes + significantBytes;
2666 *pcbEncoded = bytesNeeded;
2671 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2672 pcbEncoded, bytesNeeded)))
2674 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2675 pbEncoded = *(BYTE **)pbEncoded;
2676 *pbEncoded++ = ASN_INTEGER;
2679 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2680 pbEncoded += lenBytes;
2685 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2686 pbEncoded += lenBytes;
2688 for (; significantBytes > 0; significantBytes--)
2689 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2695 SetLastError(STATUS_ACCESS_VIOLATION);
2702 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2703 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2704 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2706 CRYPT_INTEGER_BLOB blob;
2709 /* Encode as an unsigned integer, then change the tag to enumerated */
2710 blob.cbData = sizeof(DWORD);
2711 blob.pbData = (BYTE *)pvStructInfo;
2712 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2713 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2714 if (ret && pbEncoded)
2716 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2717 pbEncoded = *(BYTE **)pbEncoded;
2718 pbEncoded[0] = ASN_ENUMERATED;
2723 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2724 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2725 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2732 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2733 * temporary buffer because the output buffer is not NULL-terminated.
2736 static const DWORD bytesNeeded = sizeof(buf) - 1;
2740 *pcbEncoded = bytesNeeded;
2745 /* Sanity check the year, this is a two-digit year format */
2746 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2748 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2750 SetLastError(CRYPT_E_BAD_ENCODE);
2755 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2756 pbEncoded, pcbEncoded, bytesNeeded)))
2758 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2759 pbEncoded = *(BYTE **)pbEncoded;
2760 buf[0] = ASN_UTCTIME;
2761 buf[1] = bytesNeeded - 2;
2762 snprintf(buf + 2, sizeof(buf) - 2,
2763 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2764 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2765 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2766 sysTime.wMinute, sysTime.wSecond);
2767 memcpy(pbEncoded, buf, bytesNeeded);
2774 SetLastError(STATUS_ACCESS_VIOLATION);
2781 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2782 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2783 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2790 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2791 * temporary buffer because the output buffer is not NULL-terminated.
2794 static const DWORD bytesNeeded = sizeof(buf) - 1;
2798 *pcbEncoded = bytesNeeded;
2803 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2806 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2807 pcbEncoded, bytesNeeded);
2810 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2811 pbEncoded = *(BYTE **)pbEncoded;
2812 buf[0] = ASN_GENERALTIME;
2813 buf[1] = bytesNeeded - 2;
2814 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2815 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2816 sysTime.wMinute, sysTime.wSecond);
2817 memcpy(pbEncoded, buf, bytesNeeded);
2823 SetLastError(STATUS_ACCESS_VIOLATION);
2830 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2831 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2832 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2840 /* Check the year, if it's in the UTCTime range call that encode func */
2841 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2843 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2844 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2845 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2847 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2848 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2853 SetLastError(STATUS_ACCESS_VIOLATION);
2860 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2861 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2862 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2868 DWORD bytesNeeded, dataLen, lenBytes, i;
2869 const CRYPT_SEQUENCE_OF_ANY *seq =
2870 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2872 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2873 dataLen += seq->rgValue[i].cbData;
2874 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2875 bytesNeeded = 1 + lenBytes + dataLen;
2878 *pcbEncoded = bytesNeeded;
2883 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2884 pcbEncoded, bytesNeeded)))
2886 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2887 pbEncoded = *(BYTE **)pbEncoded;
2888 *pbEncoded++ = ASN_SEQUENCEOF;
2889 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2890 pbEncoded += lenBytes;
2891 for (i = 0; i < seq->cValue; i++)
2893 memcpy(pbEncoded, seq->rgValue[i].pbData,
2894 seq->rgValue[i].cbData);
2895 pbEncoded += seq->rgValue[i].cbData;
2902 SetLastError(STATUS_ACCESS_VIOLATION);
2909 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2910 BYTE *pbEncoded, DWORD *pcbEncoded)
2913 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2914 struct AsnConstructedItem constructed = { 0 };
2915 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2916 DWORD cItem = 0, cSwapped = 0;
2918 switch (distPoint->DistPointName.dwDistPointNameChoice)
2920 case CRL_DIST_POINT_NO_NAME:
2923 case CRL_DIST_POINT_FULL_NAME:
2924 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2925 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2926 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2927 constructed.tag = 0;
2928 constructed.pvStructInfo = &swapped[cSwapped];
2929 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2930 items[cItem].pvStructInfo = &constructed;
2931 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2935 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2936 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2942 if (ret && distPoint->ReasonFlags.cbData)
2944 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2945 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2946 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2947 items[cItem].pvStructInfo = &swapped[cSwapped];
2948 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2952 if (ret && distPoint->CRLIssuer.cAltEntry)
2954 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2955 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2956 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2957 items[cItem].pvStructInfo = &swapped[cSwapped];
2958 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2963 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2964 pbEncoded, pcbEncoded);
2968 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2969 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2970 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2976 const CRL_DIST_POINTS_INFO *info =
2977 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2979 if (!info->cDistPoint)
2981 SetLastError(E_INVALIDARG);
2986 DWORD bytesNeeded, dataLen, lenBytes, i;
2989 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2993 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2997 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2999 /* Have to propagate index of failing character */
3005 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3006 bytesNeeded = 1 + lenBytes + dataLen;
3009 *pcbEncoded = bytesNeeded;
3014 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3015 pbEncoded, pcbEncoded, bytesNeeded)))
3017 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3018 pbEncoded = *(BYTE **)pbEncoded;
3019 *pbEncoded++ = ASN_SEQUENCEOF;
3020 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3021 pbEncoded += lenBytes;
3022 for (i = 0; ret && i < info->cDistPoint; i++)
3024 DWORD len = dataLen;
3026 ret = CRYPT_AsnEncodeDistPoint(
3027 &info->rgDistPoint[i], pbEncoded, &len);
3041 SetLastError(STATUS_ACCESS_VIOLATION);
3048 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3049 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3050 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3056 const CERT_ENHKEY_USAGE *usage =
3057 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3058 DWORD bytesNeeded = 0, lenBytes, size, i;
3061 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3063 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3064 usage->rgpszUsageIdentifier[i],
3065 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3067 bytesNeeded += size;
3069 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3070 bytesNeeded += 1 + lenBytes;
3074 *pcbEncoded = bytesNeeded;
3077 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3078 pbEncoded, pcbEncoded, bytesNeeded)))
3080 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3081 pbEncoded = *(BYTE **)pbEncoded;
3082 *pbEncoded++ = ASN_SEQUENCEOF;
3083 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3085 pbEncoded += lenBytes;
3086 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3089 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3090 usage->rgpszUsageIdentifier[i],
3091 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3096 bytesNeeded -= size;
3105 SetLastError(STATUS_ACCESS_VIOLATION);
3112 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3113 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3114 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3120 const CRL_ISSUING_DIST_POINT *point =
3121 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3122 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3123 struct AsnConstructedItem constructed = { 0 };
3124 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3125 DWORD cItem = 0, cSwapped = 0;
3128 switch (point->DistPointName.dwDistPointNameChoice)
3130 case CRL_DIST_POINT_NO_NAME:
3133 case CRL_DIST_POINT_FULL_NAME:
3134 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3135 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3136 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3137 constructed.tag = 0;
3138 constructed.pvStructInfo = &swapped[cSwapped];
3139 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3140 items[cItem].pvStructInfo = &constructed;
3141 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3146 SetLastError(E_INVALIDARG);
3149 if (ret && point->fOnlyContainsUserCerts)
3151 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3152 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3153 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3154 items[cItem].pvStructInfo = &swapped[cSwapped];
3155 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3159 if (ret && point->fOnlyContainsCACerts)
3161 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3162 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3163 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3164 items[cItem].pvStructInfo = &swapped[cSwapped];
3165 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3169 if (ret && point->OnlySomeReasonFlags.cbData)
3171 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3172 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3173 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3174 items[cItem].pvStructInfo = &swapped[cSwapped];
3175 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3179 if (ret && point->fIndirectCRL)
3181 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3182 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3183 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3184 items[cItem].pvStructInfo = &swapped[cSwapped];
3185 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3190 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3191 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3195 SetLastError(STATUS_ACCESS_VIOLATION);
3202 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3203 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3204 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3207 const CERT_GENERAL_SUBTREE *subtree =
3208 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3209 struct AsnEncodeSequenceItem items[3] = {
3210 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3213 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3214 DWORD cItem = 1, cSwapped = 0;
3216 if (subtree->dwMinimum)
3218 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3219 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3220 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3221 items[cItem].pvStructInfo = &swapped[cSwapped];
3222 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3226 if (subtree->fMaximum)
3228 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3229 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3230 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3231 items[cItem].pvStructInfo = &swapped[cSwapped];
3232 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3236 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3237 pEncodePara, pbEncoded, pcbEncoded);
3241 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3242 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3243 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3246 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3248 TRACE("%p\n", pvStructInfo);
3252 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3253 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3254 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3255 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3256 DWORD i, cItem = 0, cSwapped = 0;
3259 if (constraints->cPermittedSubtree)
3261 permitted.rgBlob = CryptMemAlloc(
3262 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3263 if (permitted.rgBlob)
3265 permitted.cBlob = constraints->cPermittedSubtree;
3266 memset(permitted.rgBlob, 0,
3267 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3268 for (i = 0; ret && i < permitted.cBlob; i++)
3269 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3270 NULL, &constraints->rgPermittedSubtree[i],
3271 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3272 (BYTE *)&permitted.rgBlob[i].pbData,
3273 &permitted.rgBlob[i].cbData);
3276 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3277 swapped[cSwapped].pvStructInfo = &permitted;
3278 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3279 items[cItem].pvStructInfo = &swapped[cSwapped];
3280 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3288 if (constraints->cExcludedSubtree)
3290 excluded.rgBlob = CryptMemAlloc(
3291 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3292 if (excluded.rgBlob)
3294 excluded.cBlob = constraints->cExcludedSubtree;
3295 memset(excluded.rgBlob, 0,
3296 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3297 for (i = 0; ret && i < excluded.cBlob; i++)
3298 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3299 NULL, &constraints->rgExcludedSubtree[i],
3300 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3301 (BYTE *)&excluded.rgBlob[i].pbData,
3302 &excluded.rgBlob[i].cbData);
3305 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3306 swapped[cSwapped].pvStructInfo = &excluded;
3307 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3308 items[cItem].pvStructInfo = &swapped[cSwapped];
3309 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3318 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3319 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3320 for (i = 0; i < permitted.cBlob; i++)
3321 LocalFree(permitted.rgBlob[i].pbData);
3322 for (i = 0; i < excluded.cBlob; i++)
3323 LocalFree(excluded.rgBlob[i].pbData);
3327 SetLastError(STATUS_ACCESS_VIOLATION);
3330 CryptMemFree(permitted.rgBlob);
3331 CryptMemFree(excluded.rgBlob);
3332 TRACE("returning %d\n", ret);
3336 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3337 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3338 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3342 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3343 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3344 struct AsnEncodeSequenceItem items[] = {
3345 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3346 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3349 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3350 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3355 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3356 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3357 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3361 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3363 SetLastError(E_INVALIDARG);
3369 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3371 if (!info->Issuer.cbData)
3372 SetLastError(E_INVALIDARG);
3375 struct AsnEncodeSequenceItem items[7] = {
3376 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3377 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3378 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3381 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3382 DWORD cItem = 3, cSwapped = 0;
3384 if (info->AuthAttrs.cAttr)
3386 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3387 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3388 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3389 items[cItem].pvStructInfo = &swapped[cSwapped];
3390 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3394 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3395 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3397 items[cItem].pvStructInfo = &info->EncryptedHash;
3398 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3400 if (info->UnauthAttrs.cAttr)
3402 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3403 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3404 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3405 items[cItem].pvStructInfo = &swapped[cSwapped];
3406 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3410 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3411 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3416 SetLastError(STATUS_ACCESS_VIOLATION);
3422 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3425 struct AsnEncodeSequenceItem items[7] = {
3426 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3428 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3429 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3430 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3431 DWORD cItem = 1, cSwapped = 0;
3434 if (signedInfo->cSignerInfo)
3436 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3437 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3438 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3439 digestAlgorithmsSet.itemOffset =
3440 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3441 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3442 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3443 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3446 items[cItem].pvStructInfo = &signedInfo->content;
3447 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3449 if (signedInfo->cCertEncoded)
3451 certSet.cItems = signedInfo->cCertEncoded;
3452 certSet.items = signedInfo->rgCertEncoded;
3453 certSet.itemSize = sizeof(CERT_BLOB);
3454 certSet.itemOffset = 0;
3455 certSet.encode = CRYPT_CopyEncodedBlob;
3456 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3457 swapped[cSwapped].pvStructInfo = &certSet;
3458 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3459 items[cItem].pvStructInfo = &swapped[cSwapped];
3460 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3464 if (signedInfo->cCrlEncoded)
3466 crlSet.cItems = signedInfo->cCrlEncoded;
3467 crlSet.items = signedInfo->rgCrlEncoded;
3468 crlSet.itemSize = sizeof(CRL_BLOB);
3469 crlSet.itemOffset = 0;
3470 crlSet.encode = CRYPT_CopyEncodedBlob;
3471 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3472 swapped[cSwapped].pvStructInfo = &crlSet;
3473 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3474 items[cItem].pvStructInfo = &swapped[cSwapped];
3475 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3479 if (ret && signedInfo->cSignerInfo)
3481 signerSet.cItems = signedInfo->cSignerInfo;
3482 signerSet.items = signedInfo->rgSignerInfo;
3483 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3484 signerSet.itemOffset = 0;
3485 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3486 items[cItem].pvStructInfo = &signerSet;
3487 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3491 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3492 items, cItem, 0, NULL, pvData, pcbData);
3497 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3498 LPCSTR lpszStructType)
3500 CryptEncodeObjectExFunc encodeFunc = NULL;
3502 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3503 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3505 SetLastError(ERROR_FILE_NOT_FOUND);
3509 if (!HIWORD(lpszStructType))
3511 switch (LOWORD(lpszStructType))
3513 case LOWORD(X509_CERT):
3514 encodeFunc = CRYPT_AsnEncodeCert;
3516 case LOWORD(X509_CERT_TO_BE_SIGNED):
3517 encodeFunc = CRYPT_AsnEncodeCertInfo;
3519 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3520 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3522 case LOWORD(X509_EXTENSIONS):
3523 encodeFunc = CRYPT_AsnEncodeExtensions;
3525 case LOWORD(X509_NAME_VALUE):
3526 encodeFunc = CRYPT_AsnEncodeNameValue;
3528 case LOWORD(X509_NAME):
3529 encodeFunc = CRYPT_AsnEncodeName;
3531 case LOWORD(X509_PUBLIC_KEY_INFO):
3532 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3534 case LOWORD(X509_AUTHORITY_KEY_ID):
3535 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3537 case LOWORD(X509_ALTERNATE_NAME):
3538 encodeFunc = CRYPT_AsnEncodeAltName;
3540 case LOWORD(X509_BASIC_CONSTRAINTS):
3541 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3543 case LOWORD(X509_BASIC_CONSTRAINTS2):
3544 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3546 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3547 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3549 case LOWORD(X509_UNICODE_NAME):
3550 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3552 case LOWORD(PKCS_CONTENT_INFO):
3553 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3555 case LOWORD(PKCS_ATTRIBUTE):
3556 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3558 case LOWORD(X509_UNICODE_NAME_VALUE):
3559 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3561 case LOWORD(X509_OCTET_STRING):
3562 encodeFunc = CRYPT_AsnEncodeOctets;
3564 case LOWORD(X509_BITS):
3565 case LOWORD(X509_KEY_USAGE):
3566 encodeFunc = CRYPT_AsnEncodeBits;
3568 case LOWORD(X509_INTEGER):
3569 encodeFunc = CRYPT_AsnEncodeInt;
3571 case LOWORD(X509_MULTI_BYTE_INTEGER):
3572 encodeFunc = CRYPT_AsnEncodeInteger;
3574 case LOWORD(X509_MULTI_BYTE_UINT):
3575 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3577 case LOWORD(X509_ENUMERATED):
3578 encodeFunc = CRYPT_AsnEncodeEnumerated;
3580 case LOWORD(X509_CHOICE_OF_TIME):
3581 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3583 case LOWORD(X509_AUTHORITY_KEY_ID2):
3584 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3586 case LOWORD(X509_SEQUENCE_OF_ANY):
3587 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3589 case LOWORD(PKCS_UTC_TIME):
3590 encodeFunc = CRYPT_AsnEncodeUtcTime;
3592 case LOWORD(X509_CRL_DIST_POINTS):
3593 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3595 case LOWORD(X509_ENHANCED_KEY_USAGE):
3596 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3598 case LOWORD(PKCS_ATTRIBUTES):
3599 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3601 case LOWORD(X509_ISSUING_DIST_POINT):
3602 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3604 case LOWORD(X509_NAME_CONSTRAINTS):
3605 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3607 case LOWORD(PKCS7_SIGNER_INFO):
3608 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3612 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3613 encodeFunc = CRYPT_AsnEncodeExtensions;
3614 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3615 encodeFunc = CRYPT_AsnEncodeUtcTime;
3616 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3617 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3618 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3619 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3620 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3621 encodeFunc = CRYPT_AsnEncodeEnumerated;
3622 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3623 encodeFunc = CRYPT_AsnEncodeBits;
3624 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3625 encodeFunc = CRYPT_AsnEncodeOctets;
3626 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3627 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3628 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3629 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3630 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3631 encodeFunc = CRYPT_AsnEncodeAltName;
3632 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3633 encodeFunc = CRYPT_AsnEncodeAltName;
3634 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3635 encodeFunc = CRYPT_AsnEncodeAltName;
3636 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3637 encodeFunc = CRYPT_AsnEncodeAltName;
3638 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3639 encodeFunc = CRYPT_AsnEncodeAltName;
3640 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3641 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3642 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3643 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3644 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3645 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3646 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3647 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3651 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3652 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3654 static HCRYPTOIDFUNCSET set = NULL;
3655 CryptEncodeObjectFunc encodeFunc = NULL;
3658 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3659 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3660 (void **)&encodeFunc, hFunc);
3664 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3665 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3667 static HCRYPTOIDFUNCSET set = NULL;
3668 CryptEncodeObjectExFunc encodeFunc = NULL;
3671 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3672 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3673 (void **)&encodeFunc, hFunc);
3677 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3678 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3681 HCRYPTOIDFUNCADDR hFunc = NULL;
3682 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3683 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3685 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3686 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3689 if (!pbEncoded && !pcbEncoded)
3691 SetLastError(ERROR_INVALID_PARAMETER);
3695 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3698 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3699 debugstr_a(lpszStructType));
3700 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3701 lpszStructType, &hFunc);
3702 if (!pCryptEncodeObject)
3703 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3704 lpszStructType, &hFunc);
3706 if (pCryptEncodeObject)
3707 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3708 pvStructInfo, pbEncoded, pcbEncoded);
3709 else if (pCryptEncodeObjectEx)
3710 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3711 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3713 CryptFreeOIDFunctionAddress(hFunc, 0);
3714 TRACE_(crypt)("returning %d\n", ret);
3718 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3719 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3720 void *pvEncoded, DWORD *pcbEncoded)
3723 HCRYPTOIDFUNCADDR hFunc = NULL;
3724 CryptEncodeObjectExFunc encodeFunc = NULL;
3726 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3727 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3728 pvEncoded, pcbEncoded);
3730 if (!pvEncoded && !pcbEncoded)
3732 SetLastError(ERROR_INVALID_PARAMETER);
3736 SetLastError(NOERROR);
3737 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3738 *(BYTE **)pvEncoded = NULL;
3739 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3742 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3743 debugstr_a(lpszStructType));
3744 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3748 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3749 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3752 CryptEncodeObjectFunc pCryptEncodeObject =
3753 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3755 if (pCryptEncodeObject)
3757 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3759 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3760 pvStructInfo, NULL, pcbEncoded);
3761 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3762 pvEncoded, pcbEncoded, *pcbEncoded)))
3763 ret = pCryptEncodeObject(dwCertEncodingType,
3764 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3768 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3769 pvStructInfo, pvEncoded, pcbEncoded);
3773 CryptFreeOIDFunctionAddress(hFunc, 0);
3774 TRACE_(crypt)("returning %d\n", ret);
3778 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3779 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3781 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3782 NULL, 0, NULL, pInfo, pcbInfo);
3785 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3786 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3787 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3791 static CHAR oid[] = szOID_RSA_RSA;
3793 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3794 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3795 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3797 if (!pszPublicKeyObjId)
3798 pszPublicKeyObjId = oid;
3799 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3803 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3806 LPBYTE pubKey = CryptMemAlloc(keySize);
3810 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3814 DWORD encodedLen = 0;
3816 ret = CryptEncodeObject(dwCertEncodingType,
3817 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3820 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3821 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3824 *pcbInfo = sizeNeeded;
3825 else if (*pcbInfo < sizeNeeded)
3827 SetLastError(ERROR_MORE_DATA);
3828 *pcbInfo = sizeNeeded;
3833 pInfo->Algorithm.pszObjId = (char *)pInfo +
3834 sizeof(CERT_PUBLIC_KEY_INFO);
3835 lstrcpyA(pInfo->Algorithm.pszObjId,
3837 pInfo->Algorithm.Parameters.cbData = 0;
3838 pInfo->Algorithm.Parameters.pbData = NULL;
3839 pInfo->PublicKey.pbData =
3840 (BYTE *)pInfo->Algorithm.pszObjId
3841 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3842 pInfo->PublicKey.cbData = encodedLen;
3843 pInfo->PublicKey.cUnusedBits = 0;
3844 ret = CryptEncodeObject(dwCertEncodingType,
3845 RSA_CSP_PUBLICKEYBLOB, pubKey,
3846 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3850 CryptMemFree(pubKey);
3855 CryptDestroyKey(key);
3860 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3861 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3862 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3864 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3865 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3866 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3868 static HCRYPTOIDFUNCSET set = NULL;
3870 ExportPublicKeyInfoExFunc exportFunc = NULL;
3871 HCRYPTOIDFUNCADDR hFunc = NULL;
3873 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3874 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3875 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3879 SetLastError(ERROR_INVALID_PARAMETER);
3883 if (pszPublicKeyObjId)
3886 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3888 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3889 0, (void **)&exportFunc, &hFunc);
3892 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3893 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3894 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3896 CryptFreeOIDFunctionAddress(hFunc, 0);
3900 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3901 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3903 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3907 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3908 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3909 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3912 DWORD pubKeySize = 0;
3914 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3915 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3917 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3918 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3921 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3925 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3926 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3931 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
3932 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3935 CryptMemFree(pubKey);
3943 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3944 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3945 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3947 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3948 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3949 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3951 static HCRYPTOIDFUNCSET set = NULL;
3953 ImportPublicKeyInfoExFunc importFunc = NULL;
3954 HCRYPTOIDFUNCADDR hFunc = NULL;
3956 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3957 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3960 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3961 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3962 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3964 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3965 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3968 CryptFreeOIDFunctionAddress(hFunc, 0);