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"
38 #define NONAMELESSUNION
44 #include "wine/debug.h"
45 #include "wine/exception.h"
46 #include "wine/unicode.h"
47 #include "crypt32_private.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
50 WINE_DECLARE_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
95 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
99 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
101 if (pEncodePara && pEncodePara->pfnAlloc)
102 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
104 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
105 if (!*(BYTE **)pbEncoded)
108 *pcbEncoded = bytesNeeded;
110 else if (bytesNeeded > *pcbEncoded)
112 *pcbEncoded = bytesNeeded;
113 SetLastError(ERROR_MORE_DATA);
117 *pcbEncoded = bytesNeeded;
121 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
123 DWORD bytesNeeded, significantBytes = 0;
131 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
132 temp <<= 8, significantBytes--)
134 bytesNeeded = significantBytes + 1;
138 *pcbEncoded = bytesNeeded;
141 if (*pcbEncoded < bytesNeeded)
143 SetLastError(ERROR_MORE_DATA);
147 *pbEncoded = (BYTE)len;
152 *pbEncoded++ = significantBytes | 0x80;
153 for (i = 0; i < significantBytes; i++)
155 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
159 *pcbEncoded = bytesNeeded;
163 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
164 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
165 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
168 DWORD i, dataLen = 0;
170 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
171 pbEncoded, *pcbEncoded);
172 for (i = 0, ret = TRUE; ret && i < cItem; i++)
174 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
175 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
176 NULL, &items[i].size);
177 /* Some functions propagate their errors through the size */
179 *pcbEncoded = items[i].size;
180 dataLen += items[i].size;
184 DWORD lenBytes, bytesNeeded;
186 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
187 bytesNeeded = 1 + lenBytes + dataLen;
189 *pcbEncoded = bytesNeeded;
192 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
193 pcbEncoded, bytesNeeded)))
195 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
196 pbEncoded = *(BYTE **)pbEncoded;
197 *pbEncoded++ = ASN_SEQUENCE;
198 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
199 pbEncoded += lenBytes;
200 for (i = 0; ret && i < cItem; i++)
202 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
203 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
204 NULL, pbEncoded, &items[i].size);
205 /* Some functions propagate their errors through the size */
207 *pcbEncoded = items[i].size;
208 pbEncoded += items[i].size;
213 TRACE("returning %d (%08x)\n", ret, GetLastError());
217 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
218 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
219 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
222 const struct AsnConstructedItem *item =
223 (const struct AsnConstructedItem *)pvStructInfo;
226 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
227 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
229 DWORD dataLen, bytesNeeded;
231 CRYPT_EncodeLen(len, NULL, &dataLen);
232 bytesNeeded = 1 + dataLen + len;
234 *pcbEncoded = bytesNeeded;
235 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
236 pbEncoded, pcbEncoded, bytesNeeded)))
238 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
239 pbEncoded = *(BYTE **)pbEncoded;
240 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
241 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
242 pbEncoded += dataLen;
243 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
244 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
248 /* Some functions propagate their errors through the size */
255 /* Some functions propagate their errors through the size */
261 struct AsnEncodeTagSwappedItem
264 const void *pvStructInfo;
265 CryptEncodeObjectExFunc encodeFunc;
268 /* Sort of a wacky hack, it encodes something using the struct
269 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
270 * given in the struct AsnEncodeTagSwappedItem.
272 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
273 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
274 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
277 const struct AsnEncodeTagSwappedItem *item =
278 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
280 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
281 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
282 if (ret && pbEncoded)
283 *pbEncoded = item->tag;
287 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
288 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
289 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
291 const DWORD *ver = (const DWORD *)pvStructInfo;
294 /* CERT_V1 is not encoded */
302 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
304 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
305 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
310 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
311 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
312 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
314 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
319 *pcbEncoded = blob->cbData;
324 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
325 pcbEncoded, blob->cbData)))
327 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
328 pbEncoded = *(BYTE **)pbEncoded;
330 memcpy(pbEncoded, blob->pbData, blob->cbData);
331 *pcbEncoded = blob->cbData;
338 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
339 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
340 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
343 /* This has two filetimes in a row, a NotBefore and a NotAfter */
344 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
345 struct AsnEncodeSequenceItem items[] = {
346 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
347 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
350 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
351 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
356 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
359 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
360 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
361 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
364 const CRYPT_ALGORITHM_IDENTIFIER *algo =
365 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
366 static const BYTE asn1Null[] = { ASN_NULL, 0 };
367 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
370 struct AsnEncodeSequenceItem items[2] = {
371 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
372 { NULL, CRYPT_CopyEncodedBlob, 0 },
375 if (algo->Parameters.cbData)
376 items[1].pvStructInfo = &algo->Parameters;
378 items[1].pvStructInfo = &nullBlob;
379 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
380 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
385 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
386 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
387 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
389 const CRYPT_ALGORITHM_IDENTIFIER *algo =
390 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
392 struct AsnEncodeSequenceItem items[] = {
393 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
394 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
397 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
398 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
403 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
404 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
405 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
411 const CERT_PUBLIC_KEY_INFO *info =
412 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
413 struct AsnEncodeSequenceItem items[] = {
414 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
415 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
418 TRACE("Encoding public key with OID %s\n",
419 debugstr_a(info->Algorithm.pszObjId));
420 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
421 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
426 SetLastError(STATUS_ACCESS_VIOLATION);
433 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
434 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
435 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
441 const CERT_SIGNED_CONTENT_INFO *info =
442 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
443 struct AsnEncodeSequenceItem items[] = {
444 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
445 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
446 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
449 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
450 items[2].encodeFunc = CRYPT_AsnEncodeBits;
451 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
452 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
457 SetLastError(STATUS_ACCESS_VIOLATION);
464 /* Like in Windows, this blithely ignores the validity of the passed-in
465 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
466 * decode properly, see CRYPT_AsnDecodeCertInfo.
468 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
469 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
470 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
476 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
477 struct AsnEncodeSequenceItem items[10] = {
478 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
479 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
480 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
481 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
482 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
483 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
484 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
487 struct AsnConstructedItem constructed[3] = { { 0 } };
488 DWORD cItem = 7, cConstructed = 0;
490 if (info->IssuerUniqueId.cbData)
492 constructed[cConstructed].tag = 1;
493 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
494 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
495 items[cItem].pvStructInfo = &constructed[cConstructed];
496 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
500 if (info->SubjectUniqueId.cbData)
502 constructed[cConstructed].tag = 2;
503 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
504 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
505 items[cItem].pvStructInfo = &constructed[cConstructed];
506 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
510 if (info->cExtension)
512 constructed[cConstructed].tag = 3;
513 constructed[cConstructed].pvStructInfo = &info->cExtension;
514 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
515 items[cItem].pvStructInfo = &constructed[cConstructed];
516 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
521 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
522 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
526 SetLastError(STATUS_ACCESS_VIOLATION);
533 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
534 BYTE *pbEncoded, DWORD *pcbEncoded)
536 struct AsnEncodeSequenceItem items[3] = {
537 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
538 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
544 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
546 if (entry->cExtension)
548 items[cItem].pvStructInfo = &entry->cExtension;
549 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
553 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
554 pbEncoded, pcbEncoded);
556 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
561 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
562 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
564 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
565 DWORD bytesNeeded, dataLen, lenBytes, i;
566 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
567 ((const BYTE *)pvStructInfo + sizeof(DWORD));
570 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
574 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
578 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
579 bytesNeeded = 1 + lenBytes + dataLen;
581 *pcbEncoded = bytesNeeded;
584 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
585 pcbEncoded, bytesNeeded)))
587 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
588 pbEncoded = *(BYTE **)pbEncoded;
589 *pbEncoded++ = ASN_SEQUENCEOF;
590 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
591 pbEncoded += lenBytes;
592 for (i = 0; i < cCRLEntry; i++)
594 DWORD size = dataLen;
596 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
605 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
606 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
607 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
609 const DWORD *ver = (const DWORD *)pvStructInfo;
612 /* CRL_V1 is not encoded */
619 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
620 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
624 /* Like in Windows, this blithely ignores the validity of the passed-in
625 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
626 * decode properly, see CRYPT_AsnDecodeCRLInfo.
628 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
629 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
630 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
636 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
637 struct AsnEncodeSequenceItem items[7] = {
638 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
639 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
640 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
641 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
644 struct AsnConstructedItem constructed[1] = { { 0 } };
645 DWORD cItem = 4, cConstructed = 0;
647 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
649 items[cItem].pvStructInfo = &info->NextUpdate;
650 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
655 items[cItem].pvStructInfo = &info->cCRLEntry;
656 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
659 if (info->cExtension)
661 constructed[cConstructed].tag = 0;
662 constructed[cConstructed].pvStructInfo = &info->cExtension;
663 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
664 items[cItem].pvStructInfo = &constructed[cConstructed];
665 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
670 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
671 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
675 SetLastError(STATUS_ACCESS_VIOLATION);
682 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
686 struct AsnEncodeSequenceItem items[3] = {
687 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
693 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
697 items[cItem].pvStructInfo = &ext->fCritical;
698 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
701 items[cItem].pvStructInfo = &ext->Value;
702 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
705 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
706 pbEncoded, pcbEncoded);
707 TRACE("returning %d (%08x)\n", ret, GetLastError());
711 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
712 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
713 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
719 DWORD bytesNeeded, dataLen, lenBytes, i;
720 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
723 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
727 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
731 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
732 bytesNeeded = 1 + lenBytes + dataLen;
734 *pcbEncoded = bytesNeeded;
737 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
738 pcbEncoded, bytesNeeded)))
740 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
741 pbEncoded = *(BYTE **)pbEncoded;
742 *pbEncoded++ = ASN_SEQUENCEOF;
743 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
744 pbEncoded += lenBytes;
745 for (i = 0; i < exts->cExtension; i++)
747 DWORD size = dataLen;
749 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
759 SetLastError(STATUS_ACCESS_VIOLATION);
766 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
767 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
768 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
770 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
771 DWORD bytesNeeded = 0, lenBytes;
776 TRACE("%s\n", debugstr_a(pszObjId));
783 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
785 SetLastError(CRYPT_E_ASN1_ERROR);
789 firstByte = val1 * 40 + val2;
790 ptr = pszObjId + firstPos;
795 /* note I assume each component is at most 32-bits long in base 2 */
796 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
798 if (val1 >= 0x10000000)
800 else if (val1 >= 0x200000)
802 else if (val1 >= 0x4000)
804 else if (val1 >= 0x80)
814 SetLastError(CRYPT_E_ASN1_ERROR);
818 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
822 bytesNeeded += 1 + lenBytes;
825 if (*pcbEncoded < bytesNeeded)
827 SetLastError(ERROR_MORE_DATA);
832 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
833 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
834 pbEncoded += lenBytes;
840 *pbEncoded++ = firstByte;
841 ptr = pszObjId + firstPos;
844 sscanf(ptr, "%d%n", &val, &pos);
846 unsigned char outBytes[5];
849 if (val >= 0x10000000)
851 else if (val >= 0x200000)
853 else if (val >= 0x4000)
855 else if (val >= 0x80)
859 for (i = numBytes; i > 0; i--)
861 outBytes[i - 1] = val & 0x7f;
864 for (i = 0; i < numBytes - 1; i++)
865 *pbEncoded++ = outBytes[i] | 0x80;
866 *pbEncoded++ = outBytes[i];
875 *pcbEncoded = bytesNeeded;
879 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
880 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
884 LPCSTR str = (LPCSTR)value->Value.pbData;
885 DWORD bytesNeeded, lenBytes, encodedLen;
887 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
888 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
889 bytesNeeded = 1 + lenBytes + encodedLen;
891 *pcbEncoded = bytesNeeded;
894 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
895 pbEncoded, pcbEncoded, bytesNeeded)))
897 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
898 pbEncoded = *(BYTE **)pbEncoded;
900 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
901 pbEncoded += lenBytes;
902 memcpy(pbEncoded, str, encodedLen);
908 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
909 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
913 LPCWSTR str = (LPCWSTR)value->Value.pbData;
914 DWORD bytesNeeded, lenBytes, strLen;
916 if (value->Value.cbData)
917 strLen = value->Value.cbData / sizeof(WCHAR);
918 else if (value->Value.pbData)
919 strLen = lstrlenW(str);
922 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
923 bytesNeeded = 1 + lenBytes + strLen * 2;
925 *pcbEncoded = bytesNeeded;
928 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
929 pbEncoded, pcbEncoded, bytesNeeded)))
933 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
934 pbEncoded = *(BYTE **)pbEncoded;
935 *pbEncoded++ = ASN_BMPSTRING;
936 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
937 pbEncoded += lenBytes;
938 for (i = 0; i < strLen; i++)
940 *pbEncoded++ = (str[i] & 0xff00) >> 8;
941 *pbEncoded++ = str[i] & 0x00ff;
948 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
949 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
953 LPCWSTR str = (LPCWSTR)value->Value.pbData;
954 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
956 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
958 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
960 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
961 bytesNeeded = 1 + lenBytes + encodedLen;
963 *pcbEncoded = bytesNeeded;
966 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
967 pbEncoded, pcbEncoded, bytesNeeded)))
969 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
970 pbEncoded = *(BYTE **)pbEncoded;
971 *pbEncoded++ = ASN_UTF8STRING;
972 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
973 pbEncoded += lenBytes;
974 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
975 bytesNeeded - lenBytes - 1, NULL, NULL);
981 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
982 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
983 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
989 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
991 switch (value->dwValueType)
993 case CERT_RDN_ANY_TYPE:
994 /* explicitly disallowed */
995 SetLastError(E_INVALIDARG);
998 case CERT_RDN_ENCODED_BLOB:
999 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1000 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1002 case CERT_RDN_OCTET_STRING:
1003 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1004 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1006 case CERT_RDN_NUMERIC_STRING:
1007 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1008 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1010 case CERT_RDN_PRINTABLE_STRING:
1011 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1012 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1014 case CERT_RDN_TELETEX_STRING:
1015 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1016 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1018 case CERT_RDN_VIDEOTEX_STRING:
1019 ret = CRYPT_AsnEncodeStringCoerce(value,
1020 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1022 case CERT_RDN_IA5_STRING:
1023 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1024 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1026 case CERT_RDN_GRAPHIC_STRING:
1027 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1028 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1030 case CERT_RDN_VISIBLE_STRING:
1031 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1032 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1034 case CERT_RDN_GENERAL_STRING:
1035 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1036 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1038 case CERT_RDN_UNIVERSAL_STRING:
1039 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1040 SetLastError(CRYPT_E_ASN1_CHOICE);
1043 case CERT_RDN_BMP_STRING:
1044 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1045 pbEncoded, pcbEncoded);
1047 case CERT_RDN_UTF8_STRING:
1048 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1049 pbEncoded, pcbEncoded);
1052 SetLastError(CRYPT_E_ASN1_CHOICE);
1058 SetLastError(STATUS_ACCESS_VIOLATION);
1065 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1066 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1067 BYTE *pbEncoded, DWORD *pcbEncoded)
1069 DWORD bytesNeeded = 0, lenBytes, size;
1072 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1073 0, NULL, NULL, &size);
1076 bytesNeeded += size;
1077 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1078 * with dwValueType, so "cast" it to get its encoded size
1080 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1081 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1084 bytesNeeded += size;
1085 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1086 bytesNeeded += 1 + lenBytes;
1089 if (*pcbEncoded < bytesNeeded)
1091 SetLastError(ERROR_MORE_DATA);
1096 *pbEncoded++ = ASN_SEQUENCE;
1097 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1099 pbEncoded += lenBytes;
1100 size = bytesNeeded - 1 - lenBytes;
1101 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1102 attr->pszObjId, 0, NULL, pbEncoded, &size);
1106 size = bytesNeeded - 1 - lenBytes - size;
1107 ret = nameValueEncodeFunc(dwCertEncodingType,
1108 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1109 0, NULL, pbEncoded, &size);
1116 *pcbEncoded = bytesNeeded;
1120 /* Have to propagate index of failing character */
1127 static int BLOBComp(const void *l, const void *r)
1129 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1132 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1133 ret = a->cbData - b->cbData;
1137 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1139 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1140 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1141 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1143 const CRYPT_BLOB_ARRAY *set = (const CRYPT_BLOB_ARRAY *)pvStructInfo;
1144 DWORD bytesNeeded = 0, lenBytes, i;
1147 for (i = 0; i < set->cBlob; i++)
1148 bytesNeeded += set->rgBlob[i].cbData;
1149 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1150 bytesNeeded += 1 + lenBytes;
1153 *pcbEncoded = bytesNeeded;
1156 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1157 pbEncoded, pcbEncoded, bytesNeeded)))
1159 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1160 pbEncoded = *(BYTE **)pbEncoded;
1161 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1162 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1163 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1164 pbEncoded += lenBytes;
1165 for (i = 0; ret && i < set->cBlob; i++)
1167 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1168 pbEncoded += set->rgBlob[i].cbData;
1174 struct DERSetDescriptor
1180 CryptEncodeObjectExFunc encode;
1183 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1184 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1185 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1187 const struct DERSetDescriptor *desc =
1188 (const struct DERSetDescriptor *)pvStructInfo;
1189 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1195 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1200 setOf.cBlob = desc->cItems;
1201 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1204 for (i = 0; ret && i < setOf.cBlob; i++)
1206 ret = desc->encode(dwCertEncodingType, lpszStructType,
1207 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1208 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1211 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1212 if (!setOf.rgBlob[i].pbData)
1215 ret = desc->encode(dwCertEncodingType, lpszStructType,
1216 (const BYTE *)desc->items + i * desc->itemSize +
1217 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1218 &setOf.rgBlob[i].cbData);
1220 /* Some functions propagate their errors through the size */
1222 *pcbEncoded = setOf.rgBlob[i].cbData;
1226 DWORD bytesNeeded = 0, lenBytes;
1229 for (i = 0; i < setOf.cBlob; i++)
1230 bytesNeeded += setOf.rgBlob[i].cbData;
1231 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1232 bytesNeeded += 1 + lenBytes;
1234 *pcbEncoded = bytesNeeded;
1235 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1236 pbEncoded, pcbEncoded, bytesNeeded)))
1238 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1239 pbEncoded = *(BYTE **)pbEncoded;
1240 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1242 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1243 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1244 pbEncoded += lenBytes;
1245 for (i = 0; i < setOf.cBlob; i++)
1247 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1248 setOf.rgBlob[i].cbData);
1249 pbEncoded += setOf.rgBlob[i].cbData;
1253 for (i = 0; i < setOf.cBlob; i++)
1254 CryptMemFree(setOf.rgBlob[i].pbData);
1255 CryptMemFree(setOf.rgBlob);
1259 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1260 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1264 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1273 setOf.cBlob = rdn->cRDNAttr;
1274 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1275 sizeof(CRYPT_DER_BLOB));
1279 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1281 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1283 setOf.rgBlob[i].cbData = 0;
1284 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1285 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1288 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1289 if (!setOf.rgBlob[i].pbData)
1292 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1293 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1294 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1298 /* Have to propagate index of failing character */
1299 *pcbEncoded = setOf.rgBlob[i].cbData;
1303 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1304 pbEncoded, pcbEncoded);
1305 for (i = 0; i < setOf.cBlob; i++)
1306 CryptMemFree(setOf.rgBlob[i].pbData);
1310 SetLastError(STATUS_ACCESS_VIOLATION);
1314 CryptMemFree(setOf.rgBlob);
1318 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1319 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1320 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1322 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1323 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1324 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1327 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1330 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1331 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1332 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1334 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1335 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1339 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1340 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1341 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1347 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1348 DWORD bytesNeeded = 0, lenBytes, size, i;
1350 TRACE("encoding name with %d RDNs\n", info->cRDN);
1352 for (i = 0; ret && i < info->cRDN; i++)
1354 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1355 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1357 bytesNeeded += size;
1361 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1362 bytesNeeded += 1 + lenBytes;
1366 *pcbEncoded = bytesNeeded;
1369 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1370 pbEncoded, pcbEncoded, bytesNeeded)))
1372 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1373 pbEncoded = *(BYTE **)pbEncoded;
1374 *pbEncoded++ = ASN_SEQUENCEOF;
1375 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1377 pbEncoded += lenBytes;
1378 for (i = 0; ret && i < info->cRDN; i++)
1381 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1382 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1387 bytesNeeded -= size;
1398 SetLastError(STATUS_ACCESS_VIOLATION);
1405 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1406 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1407 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1413 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1415 if (!attr->pszObjId)
1416 SetLastError(E_INVALIDARG);
1419 struct AsnEncodeSequenceItem items[2] = {
1420 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1421 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1424 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1425 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1431 SetLastError(STATUS_ACCESS_VIOLATION);
1437 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1438 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1439 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1445 const CRYPT_ATTRIBUTES *attributes =
1446 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1447 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1448 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1450 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1451 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1455 SetLastError(STATUS_ACCESS_VIOLATION);
1461 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1462 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1463 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1464 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1467 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1468 struct AsnEncodeSequenceItem items[2] = {
1469 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1472 struct AsnConstructedItem constructed = { 0 };
1475 if (info->Content.cbData)
1477 constructed.tag = 0;
1478 constructed.pvStructInfo = &info->Content;
1479 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1480 items[cItem].pvStructInfo = &constructed;
1481 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1484 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1485 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1488 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1489 void *pvData, DWORD *pcbData)
1491 struct AsnEncodeSequenceItem items[] = {
1492 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1493 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1495 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1496 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1499 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1500 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1503 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1504 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1505 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1511 const CRYPT_CONTENT_INFO *info =
1512 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1514 if (!info->pszObjId)
1515 SetLastError(E_INVALIDARG);
1517 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1518 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1523 SetLastError(STATUS_ACCESS_VIOLATION);
1529 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1530 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1534 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1535 DWORD bytesNeeded, lenBytes, encodedLen;
1537 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1539 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1540 bytesNeeded = 1 + lenBytes + encodedLen;
1542 *pcbEncoded = bytesNeeded;
1545 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1546 pbEncoded, pcbEncoded, bytesNeeded)))
1550 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1551 pbEncoded = *(BYTE **)pbEncoded;
1553 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1554 pbEncoded += lenBytes;
1555 for (i = 0; i < encodedLen; i++)
1556 *pbEncoded++ = (BYTE)str[i];
1562 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1563 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1567 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1568 DWORD bytesNeeded, lenBytes, encodedLen;
1570 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1572 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1573 bytesNeeded = 1 + lenBytes + encodedLen;
1575 *pcbEncoded = bytesNeeded;
1578 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1579 pbEncoded, pcbEncoded, bytesNeeded)))
1583 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1584 pbEncoded = *(BYTE **)pbEncoded;
1585 *pbEncoded++ = ASN_NUMERICSTRING;
1586 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1587 pbEncoded += lenBytes;
1588 for (i = 0; ret && i < encodedLen; i++)
1590 if (isdigitW(str[i]))
1591 *pbEncoded++ = (BYTE)str[i];
1595 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1604 static inline int isprintableW(WCHAR wc)
1606 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1607 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1608 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1611 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1612 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1616 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1617 DWORD bytesNeeded, lenBytes, encodedLen;
1619 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1621 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1622 bytesNeeded = 1 + lenBytes + encodedLen;
1624 *pcbEncoded = bytesNeeded;
1627 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1628 pbEncoded, pcbEncoded, bytesNeeded)))
1632 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1633 pbEncoded = *(BYTE **)pbEncoded;
1634 *pbEncoded++ = ASN_PRINTABLESTRING;
1635 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1636 pbEncoded += lenBytes;
1637 for (i = 0; ret && i < encodedLen; i++)
1639 if (isprintableW(str[i]))
1640 *pbEncoded++ = (BYTE)str[i];
1644 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1653 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1654 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1658 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1659 DWORD bytesNeeded, lenBytes, encodedLen;
1661 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1663 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1664 bytesNeeded = 1 + lenBytes + encodedLen;
1666 *pcbEncoded = bytesNeeded;
1669 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1670 pbEncoded, pcbEncoded, bytesNeeded)))
1674 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1675 pbEncoded = *(BYTE **)pbEncoded;
1676 *pbEncoded++ = ASN_IA5STRING;
1677 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1678 pbEncoded += lenBytes;
1679 for (i = 0; ret && i < encodedLen; i++)
1682 *pbEncoded++ = (BYTE)str[i];
1686 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1695 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1696 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1700 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1701 DWORD bytesNeeded, lenBytes, strLen;
1703 /* FIXME: doesn't handle composite characters */
1704 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1706 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1707 bytesNeeded = 1 + lenBytes + strLen * 4;
1709 *pcbEncoded = bytesNeeded;
1712 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1713 pbEncoded, pcbEncoded, bytesNeeded)))
1717 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1718 pbEncoded = *(BYTE **)pbEncoded;
1719 *pbEncoded++ = ASN_UNIVERSALSTRING;
1720 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1721 pbEncoded += lenBytes;
1722 for (i = 0; i < strLen; i++)
1726 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1727 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1734 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1735 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1736 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1742 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1744 switch (value->dwValueType)
1746 case CERT_RDN_ANY_TYPE:
1747 case CERT_RDN_ENCODED_BLOB:
1748 case CERT_RDN_OCTET_STRING:
1749 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1751 case CERT_RDN_NUMERIC_STRING:
1752 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1753 pbEncoded, pcbEncoded);
1755 case CERT_RDN_PRINTABLE_STRING:
1756 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1757 pbEncoded, pcbEncoded);
1759 case CERT_RDN_TELETEX_STRING:
1760 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1761 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1763 case CERT_RDN_VIDEOTEX_STRING:
1764 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1765 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1767 case CERT_RDN_IA5_STRING:
1768 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1769 pbEncoded, pcbEncoded);
1771 case CERT_RDN_GRAPHIC_STRING:
1772 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1773 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1775 case CERT_RDN_VISIBLE_STRING:
1776 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1777 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1779 case CERT_RDN_GENERAL_STRING:
1780 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1781 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1783 case CERT_RDN_UNIVERSAL_STRING:
1784 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1785 pbEncoded, pcbEncoded);
1787 case CERT_RDN_BMP_STRING:
1788 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1789 pbEncoded, pcbEncoded);
1791 case CERT_RDN_UTF8_STRING:
1792 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1793 pbEncoded, pcbEncoded);
1796 SetLastError(CRYPT_E_ASN1_CHOICE);
1801 SetLastError(STATUS_ACCESS_VIOLATION);
1807 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1808 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1809 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1815 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1816 DWORD bytesNeeded = 0, lenBytes, size, i;
1818 TRACE("encoding name with %d RDNs\n", info->cRDN);
1820 for (i = 0; ret && i < info->cRDN; i++)
1822 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1823 CRYPT_AsnEncodeNameValue, NULL, &size);
1825 bytesNeeded += size;
1827 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1828 bytesNeeded += 1 + lenBytes;
1832 *pcbEncoded = bytesNeeded;
1835 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1836 pbEncoded, pcbEncoded, bytesNeeded)))
1838 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1839 pbEncoded = *(BYTE **)pbEncoded;
1840 *pbEncoded++ = ASN_SEQUENCEOF;
1841 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1843 pbEncoded += lenBytes;
1844 for (i = 0; ret && i < info->cRDN; i++)
1847 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1848 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1853 bytesNeeded -= size;
1862 SetLastError(STATUS_ACCESS_VIOLATION);
1869 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1870 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1871 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1873 BOOL val = *(const BOOL *)pvStructInfo, ret;
1882 else if (*pcbEncoded < 3)
1885 SetLastError(ERROR_MORE_DATA);
1891 *pbEncoded++ = ASN_BOOL;
1893 *pbEncoded++ = val ? 0xff : 0;
1896 TRACE("returning %d (%08x)\n", ret, GetLastError());
1900 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1901 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1902 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1904 const CERT_ALT_NAME_ENTRY *entry =
1905 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1911 switch (entry->dwAltNameChoice)
1913 case CERT_ALT_NAME_RFC822_NAME:
1914 case CERT_ALT_NAME_DNS_NAME:
1915 case CERT_ALT_NAME_URL:
1916 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1917 if (entry->u.pwszURL)
1921 /* Not + 1: don't encode the NULL-terminator */
1922 dataLen = lstrlenW(entry->u.pwszURL);
1923 for (i = 0; ret && i < dataLen; i++)
1925 if (entry->u.pwszURL[i] > 0x7f)
1927 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1936 case CERT_ALT_NAME_DIRECTORY_NAME:
1937 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1938 dataLen = entry->u.DirectoryName.cbData;
1940 case CERT_ALT_NAME_IP_ADDRESS:
1941 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1942 dataLen = entry->u.IPAddress.cbData;
1944 case CERT_ALT_NAME_REGISTERED_ID:
1946 struct AsnEncodeTagSwappedItem swapped =
1947 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1948 CRYPT_AsnEncodeOid };
1950 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1953 case CERT_ALT_NAME_OTHER_NAME:
1954 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1957 SetLastError(E_INVALIDARG);
1962 DWORD bytesNeeded, lenBytes;
1964 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1965 bytesNeeded = 1 + dataLen + lenBytes;
1967 *pcbEncoded = bytesNeeded;
1968 else if (*pcbEncoded < bytesNeeded)
1970 SetLastError(ERROR_MORE_DATA);
1971 *pcbEncoded = bytesNeeded;
1977 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1978 pbEncoded += lenBytes;
1979 switch (entry->dwAltNameChoice)
1981 case CERT_ALT_NAME_RFC822_NAME:
1982 case CERT_ALT_NAME_DNS_NAME:
1983 case CERT_ALT_NAME_URL:
1987 for (i = 0; i < dataLen; i++)
1988 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1991 case CERT_ALT_NAME_DIRECTORY_NAME:
1992 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
1994 case CERT_ALT_NAME_IP_ADDRESS:
1995 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1999 *pcbEncoded = bytesNeeded;
2002 TRACE("returning %d (%08x)\n", ret, GetLastError());
2006 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2007 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2008 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2014 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2015 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2020 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2025 for (i = 0; i < newBlob.cbData; i++)
2026 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2032 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2033 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2034 CryptMemFree(newBlob.pbData);
2038 SetLastError(STATUS_ACCESS_VIOLATION);
2045 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2046 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2047 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2053 const CERT_AUTHORITY_KEY_ID_INFO *info =
2054 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2055 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2056 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2057 struct AsnConstructedItem constructed = { 0 };
2058 DWORD cItem = 0, cSwapped = 0;
2060 if (info->KeyId.cbData)
2062 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2063 swapped[cSwapped].pvStructInfo = &info->KeyId;
2064 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2065 items[cItem].pvStructInfo = &swapped[cSwapped];
2066 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2070 if (info->CertIssuer.cbData)
2072 constructed.tag = 1;
2073 constructed.pvStructInfo = &info->CertIssuer;
2074 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2075 items[cItem].pvStructInfo = &constructed;
2076 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2079 if (info->CertSerialNumber.cbData)
2081 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2082 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2083 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2084 items[cItem].pvStructInfo = &swapped[cSwapped];
2085 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2089 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2090 pEncodePara, pbEncoded, pcbEncoded);
2094 SetLastError(STATUS_ACCESS_VIOLATION);
2101 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2102 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2103 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2109 const CERT_ALT_NAME_INFO *info =
2110 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2111 DWORD bytesNeeded, dataLen, lenBytes, i;
2114 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2115 * can't encode an erroneous entry index if it's bigger than this.
2117 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2121 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2122 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2125 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2127 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2128 * the bad character, now set the index of the bad
2131 *pcbEncoded = (BYTE)i <<
2132 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2137 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2138 bytesNeeded = 1 + lenBytes + dataLen;
2141 *pcbEncoded = bytesNeeded;
2146 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2147 pbEncoded, pcbEncoded, bytesNeeded)))
2149 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2150 pbEncoded = *(BYTE **)pbEncoded;
2151 *pbEncoded++ = ASN_SEQUENCEOF;
2152 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2153 pbEncoded += lenBytes;
2154 for (i = 0; ret && i < info->cAltEntry; i++)
2156 DWORD len = dataLen;
2158 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2159 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2172 SetLastError(STATUS_ACCESS_VIOLATION);
2179 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2180 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2181 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2187 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2188 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2189 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2190 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2191 DWORD cItem = 0, cSwapped = 0;
2193 if (info->KeyId.cbData)
2195 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2196 swapped[cSwapped].pvStructInfo = &info->KeyId;
2197 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2198 items[cItem].pvStructInfo = &swapped[cSwapped];
2199 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2203 if (info->AuthorityCertIssuer.cAltEntry)
2205 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2206 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2207 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2208 items[cItem].pvStructInfo = &swapped[cSwapped];
2209 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2213 if (info->AuthorityCertSerialNumber.cbData)
2215 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2216 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2217 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2218 items[cItem].pvStructInfo = &swapped[cSwapped];
2219 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2223 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2224 pEncodePara, pbEncoded, pcbEncoded);
2228 SetLastError(STATUS_ACCESS_VIOLATION);
2235 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2236 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2237 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2243 const CERT_BASIC_CONSTRAINTS_INFO *info =
2244 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2245 struct AsnEncodeSequenceItem items[3] = {
2246 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2251 if (info->fPathLenConstraint)
2253 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2254 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2257 if (info->cSubtreesConstraint)
2259 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2260 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2263 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2264 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2268 SetLastError(STATUS_ACCESS_VIOLATION);
2275 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2276 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2277 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2283 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2284 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2285 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2290 items[cItem].pvStructInfo = &info->fCA;
2291 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2294 if (info->fPathLenConstraint)
2296 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2297 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2300 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2301 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2305 SetLastError(STATUS_ACCESS_VIOLATION);
2312 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2313 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2314 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2320 const BLOBHEADER *hdr =
2321 (const BLOBHEADER *)pvStructInfo;
2323 if (hdr->bType != PUBLICKEYBLOB)
2325 SetLastError(E_INVALIDARG);
2330 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2331 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2332 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2333 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2334 struct AsnEncodeSequenceItem items[] = {
2335 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2336 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2339 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2340 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2346 SetLastError(STATUS_ACCESS_VIOLATION);
2353 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2354 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2355 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2361 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2362 DWORD bytesNeeded, lenBytes;
2364 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2365 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2367 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2368 bytesNeeded = 1 + lenBytes + blob->cbData;
2371 *pcbEncoded = bytesNeeded;
2376 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2377 pcbEncoded, bytesNeeded)))
2379 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2380 pbEncoded = *(BYTE **)pbEncoded;
2381 *pbEncoded++ = ASN_OCTETSTRING;
2382 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2383 pbEncoded += lenBytes;
2385 memcpy(pbEncoded, blob->pbData, blob->cbData);
2391 SetLastError(STATUS_ACCESS_VIOLATION);
2395 TRACE("returning %d (%08x)\n", ret, GetLastError());
2399 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2400 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2401 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2407 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2408 DWORD bytesNeeded, lenBytes, dataBytes;
2411 /* yep, MS allows cUnusedBits to be >= 8 */
2412 if (!blob->cUnusedBits)
2414 dataBytes = blob->cbData;
2417 else if (blob->cbData * 8 > blob->cUnusedBits)
2419 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2420 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2428 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2429 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2432 *pcbEncoded = bytesNeeded;
2437 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2438 pcbEncoded, bytesNeeded)))
2440 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2441 pbEncoded = *(BYTE **)pbEncoded;
2442 *pbEncoded++ = ASN_BITSTRING;
2443 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2444 pbEncoded += lenBytes;
2445 *pbEncoded++ = unusedBits;
2448 BYTE mask = 0xff << unusedBits;
2452 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2453 pbEncoded += dataBytes - 1;
2455 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2462 SetLastError(STATUS_ACCESS_VIOLATION);
2469 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2470 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2471 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2477 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2478 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2483 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2488 for (i = 0; i < newBlob.cbData; i++)
2489 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2495 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2496 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2497 CryptMemFree(newBlob.pbData);
2501 SetLastError(STATUS_ACCESS_VIOLATION);
2508 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2509 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2510 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2512 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2514 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2515 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2518 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2519 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2520 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2526 DWORD significantBytes, lenBytes;
2527 BYTE padByte = 0, bytesNeeded;
2529 const CRYPT_INTEGER_BLOB *blob =
2530 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2532 significantBytes = blob->cbData;
2533 if (significantBytes)
2535 if (blob->pbData[significantBytes - 1] & 0x80)
2537 /* negative, lop off leading (little-endian) 0xffs */
2538 for (; significantBytes > 0 &&
2539 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2541 if (blob->pbData[significantBytes - 1] < 0x80)
2549 /* positive, lop off leading (little-endian) zeroes */
2550 for (; significantBytes > 0 &&
2551 !blob->pbData[significantBytes - 1]; significantBytes--)
2553 if (significantBytes == 0)
2554 significantBytes = 1;
2555 if (blob->pbData[significantBytes - 1] > 0x7f)
2563 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2565 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2566 bytesNeeded = 1 + lenBytes + significantBytes;
2571 *pcbEncoded = bytesNeeded;
2576 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2577 pcbEncoded, bytesNeeded)))
2579 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2580 pbEncoded = *(BYTE **)pbEncoded;
2581 *pbEncoded++ = ASN_INTEGER;
2584 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2585 pbEncoded += lenBytes;
2586 *pbEncoded++ = padByte;
2590 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2591 pbEncoded += lenBytes;
2593 for (; significantBytes > 0; significantBytes--)
2594 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2600 SetLastError(STATUS_ACCESS_VIOLATION);
2607 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2608 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2609 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2615 DWORD significantBytes, lenBytes;
2618 const CRYPT_INTEGER_BLOB *blob =
2619 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2621 significantBytes = blob->cbData;
2622 if (significantBytes)
2624 /* positive, lop off leading (little-endian) zeroes */
2625 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2628 if (significantBytes == 0)
2629 significantBytes = 1;
2630 if (blob->pbData[significantBytes - 1] > 0x7f)
2634 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2636 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2637 bytesNeeded = 1 + lenBytes + significantBytes;
2642 *pcbEncoded = bytesNeeded;
2647 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2648 pcbEncoded, bytesNeeded)))
2650 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2651 pbEncoded = *(BYTE **)pbEncoded;
2652 *pbEncoded++ = ASN_INTEGER;
2655 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2656 pbEncoded += lenBytes;
2661 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2662 pbEncoded += lenBytes;
2664 for (; significantBytes > 0; significantBytes--)
2665 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2671 SetLastError(STATUS_ACCESS_VIOLATION);
2678 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2679 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2680 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2682 CRYPT_INTEGER_BLOB blob;
2685 /* Encode as an unsigned integer, then change the tag to enumerated */
2686 blob.cbData = sizeof(DWORD);
2687 blob.pbData = (BYTE *)pvStructInfo;
2688 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2689 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2690 if (ret && pbEncoded)
2692 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2693 pbEncoded = *(BYTE **)pbEncoded;
2694 pbEncoded[0] = ASN_ENUMERATED;
2699 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2700 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2701 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2708 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2709 * temporary buffer because the output buffer is not NULL-terminated.
2712 static const DWORD bytesNeeded = sizeof(buf) - 1;
2716 *pcbEncoded = bytesNeeded;
2721 /* Sanity check the year, this is a two-digit year format */
2722 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2724 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2726 SetLastError(CRYPT_E_BAD_ENCODE);
2731 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2732 pbEncoded, pcbEncoded, bytesNeeded)))
2734 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2735 pbEncoded = *(BYTE **)pbEncoded;
2736 buf[0] = ASN_UTCTIME;
2737 buf[1] = bytesNeeded - 2;
2738 snprintf(buf + 2, sizeof(buf) - 2,
2739 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2740 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2741 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2742 sysTime.wMinute, sysTime.wSecond);
2743 memcpy(pbEncoded, buf, bytesNeeded);
2750 SetLastError(STATUS_ACCESS_VIOLATION);
2757 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2758 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2759 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2766 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2767 * temporary buffer because the output buffer is not NULL-terminated.
2770 static const DWORD bytesNeeded = sizeof(buf) - 1;
2774 *pcbEncoded = bytesNeeded;
2779 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2782 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2783 pcbEncoded, bytesNeeded);
2786 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2787 pbEncoded = *(BYTE **)pbEncoded;
2788 buf[0] = ASN_GENERALTIME;
2789 buf[1] = bytesNeeded - 2;
2790 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2791 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2792 sysTime.wMinute, sysTime.wSecond);
2793 memcpy(pbEncoded, buf, bytesNeeded);
2799 SetLastError(STATUS_ACCESS_VIOLATION);
2806 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2807 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2808 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2816 /* Check the year, if it's in the UTCTime range call that encode func */
2817 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2819 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2820 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2821 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2823 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2824 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2829 SetLastError(STATUS_ACCESS_VIOLATION);
2836 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2837 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2838 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2844 DWORD bytesNeeded, dataLen, lenBytes, i;
2845 const CRYPT_SEQUENCE_OF_ANY *seq =
2846 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2848 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2849 dataLen += seq->rgValue[i].cbData;
2850 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2851 bytesNeeded = 1 + lenBytes + dataLen;
2854 *pcbEncoded = bytesNeeded;
2859 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2860 pcbEncoded, bytesNeeded)))
2862 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2863 pbEncoded = *(BYTE **)pbEncoded;
2864 *pbEncoded++ = ASN_SEQUENCEOF;
2865 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2866 pbEncoded += lenBytes;
2867 for (i = 0; i < seq->cValue; i++)
2869 memcpy(pbEncoded, seq->rgValue[i].pbData,
2870 seq->rgValue[i].cbData);
2871 pbEncoded += seq->rgValue[i].cbData;
2878 SetLastError(STATUS_ACCESS_VIOLATION);
2885 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2886 BYTE *pbEncoded, DWORD *pcbEncoded)
2889 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2890 struct AsnConstructedItem constructed = { 0 };
2891 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2892 DWORD cItem = 0, cSwapped = 0;
2894 switch (distPoint->DistPointName.dwDistPointNameChoice)
2896 case CRL_DIST_POINT_NO_NAME:
2899 case CRL_DIST_POINT_FULL_NAME:
2900 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2901 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2902 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2903 constructed.tag = 0;
2904 constructed.pvStructInfo = &swapped[cSwapped];
2905 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2906 items[cItem].pvStructInfo = &constructed;
2907 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2911 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2912 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2918 if (ret && distPoint->ReasonFlags.cbData)
2920 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2921 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2922 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2923 items[cItem].pvStructInfo = &swapped[cSwapped];
2924 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2928 if (ret && distPoint->CRLIssuer.cAltEntry)
2930 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2931 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2932 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2933 items[cItem].pvStructInfo = &swapped[cSwapped];
2934 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2939 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2940 pbEncoded, pcbEncoded);
2944 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2945 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2946 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2952 const CRL_DIST_POINTS_INFO *info =
2953 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2955 if (!info->cDistPoint)
2957 SetLastError(E_INVALIDARG);
2962 DWORD bytesNeeded, dataLen, lenBytes, i;
2965 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2969 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2973 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2975 /* Have to propagate index of failing character */
2981 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2982 bytesNeeded = 1 + lenBytes + dataLen;
2985 *pcbEncoded = bytesNeeded;
2990 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2991 pbEncoded, pcbEncoded, bytesNeeded)))
2993 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2994 pbEncoded = *(BYTE **)pbEncoded;
2995 *pbEncoded++ = ASN_SEQUENCEOF;
2996 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2997 pbEncoded += lenBytes;
2998 for (i = 0; ret && i < info->cDistPoint; i++)
3000 DWORD len = dataLen;
3002 ret = CRYPT_AsnEncodeDistPoint(
3003 &info->rgDistPoint[i], pbEncoded, &len);
3017 SetLastError(STATUS_ACCESS_VIOLATION);
3024 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3025 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3026 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3032 const CERT_ENHKEY_USAGE *usage =
3033 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3034 DWORD bytesNeeded = 0, lenBytes, size, i;
3037 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3039 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3040 usage->rgpszUsageIdentifier[i],
3041 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3043 bytesNeeded += size;
3045 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3046 bytesNeeded += 1 + lenBytes;
3050 *pcbEncoded = bytesNeeded;
3053 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3054 pbEncoded, pcbEncoded, bytesNeeded)))
3056 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3057 pbEncoded = *(BYTE **)pbEncoded;
3058 *pbEncoded++ = ASN_SEQUENCEOF;
3059 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3061 pbEncoded += lenBytes;
3062 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3065 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3066 usage->rgpszUsageIdentifier[i],
3067 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3072 bytesNeeded -= size;
3081 SetLastError(STATUS_ACCESS_VIOLATION);
3088 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3089 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3090 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3096 const CRL_ISSUING_DIST_POINT *point =
3097 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3098 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3099 struct AsnConstructedItem constructed = { 0 };
3100 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3101 DWORD cItem = 0, cSwapped = 0;
3104 switch (point->DistPointName.dwDistPointNameChoice)
3106 case CRL_DIST_POINT_NO_NAME:
3109 case CRL_DIST_POINT_FULL_NAME:
3110 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3111 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3112 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3113 constructed.tag = 0;
3114 constructed.pvStructInfo = &swapped[cSwapped];
3115 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3116 items[cItem].pvStructInfo = &constructed;
3117 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3122 SetLastError(E_INVALIDARG);
3125 if (ret && point->fOnlyContainsUserCerts)
3127 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3128 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3129 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3130 items[cItem].pvStructInfo = &swapped[cSwapped];
3131 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3135 if (ret && point->fOnlyContainsCACerts)
3137 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3138 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3139 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3140 items[cItem].pvStructInfo = &swapped[cSwapped];
3141 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3145 if (ret && point->OnlySomeReasonFlags.cbData)
3147 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3148 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3149 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3150 items[cItem].pvStructInfo = &swapped[cSwapped];
3151 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3155 if (ret && point->fIndirectCRL)
3157 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3158 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3159 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3160 items[cItem].pvStructInfo = &swapped[cSwapped];
3161 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3166 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3167 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3171 SetLastError(STATUS_ACCESS_VIOLATION);
3178 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3183 const CERT_GENERAL_SUBTREE *subtree =
3184 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3185 struct AsnEncodeSequenceItem items[3] = {
3186 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3189 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3190 DWORD cItem = 1, cSwapped = 0;
3192 if (subtree->dwMinimum)
3194 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3195 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3196 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3197 items[cItem].pvStructInfo = &swapped[cSwapped];
3198 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3202 if (subtree->fMaximum)
3204 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3205 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3206 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3207 items[cItem].pvStructInfo = &swapped[cSwapped];
3208 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3212 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3213 pEncodePara, pbEncoded, pcbEncoded);
3217 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3218 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3219 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3222 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
3224 TRACE("%p\n", pvStructInfo);
3228 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3229 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3230 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3231 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3232 DWORD i, cItem = 0, cSwapped = 0;
3235 if (constraints->cPermittedSubtree)
3237 permitted.rgBlob = CryptMemAlloc(
3238 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3239 if (permitted.rgBlob)
3241 permitted.cBlob = constraints->cPermittedSubtree;
3242 memset(permitted.rgBlob, 0,
3243 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
3244 for (i = 0; ret && i < permitted.cBlob; i++)
3245 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3246 NULL, &constraints->rgPermittedSubtree[i],
3247 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3248 (BYTE *)&permitted.rgBlob[i].pbData,
3249 &permitted.rgBlob[i].cbData);
3252 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3253 swapped[cSwapped].pvStructInfo = &permitted;
3254 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3255 items[cItem].pvStructInfo = &swapped[cSwapped];
3256 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3264 if (constraints->cExcludedSubtree)
3266 excluded.rgBlob = CryptMemAlloc(
3267 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3268 if (excluded.rgBlob)
3270 excluded.cBlob = constraints->cExcludedSubtree;
3271 memset(excluded.rgBlob, 0,
3272 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
3273 for (i = 0; ret && i < excluded.cBlob; i++)
3274 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3275 NULL, &constraints->rgExcludedSubtree[i],
3276 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3277 (BYTE *)&excluded.rgBlob[i].pbData,
3278 &excluded.rgBlob[i].cbData);
3281 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3282 swapped[cSwapped].pvStructInfo = &excluded;
3283 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3284 items[cItem].pvStructInfo = &swapped[cSwapped];
3285 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3294 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3295 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3296 for (i = 0; i < permitted.cBlob; i++)
3297 LocalFree(permitted.rgBlob[i].pbData);
3298 for (i = 0; i < excluded.cBlob; i++)
3299 LocalFree(excluded.rgBlob[i].pbData);
3303 SetLastError(STATUS_ACCESS_VIOLATION);
3306 CryptMemFree(permitted.rgBlob);
3307 CryptMemFree(excluded.rgBlob);
3308 TRACE("returning %d\n", ret);
3312 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3313 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3314 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3318 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3319 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3320 struct AsnEncodeSequenceItem items[] = {
3321 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3322 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3325 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3326 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3331 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3332 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3333 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3337 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3339 SetLastError(E_INVALIDARG);
3345 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3347 if (!info->Issuer.cbData)
3348 SetLastError(E_INVALIDARG);
3351 struct AsnEncodeSequenceItem items[7] = {
3352 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3353 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3354 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3357 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3358 DWORD cItem = 3, cSwapped = 0;
3360 if (info->AuthAttrs.cAttr)
3362 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3363 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3364 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3365 items[cItem].pvStructInfo = &swapped[cSwapped];
3366 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3370 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3371 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3373 items[cItem].pvStructInfo = &info->EncryptedHash;
3374 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3376 if (info->UnauthAttrs.cAttr)
3378 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3379 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3380 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3381 items[cItem].pvStructInfo = &swapped[cSwapped];
3382 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3386 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3387 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3392 SetLastError(STATUS_ACCESS_VIOLATION);
3398 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3401 struct AsnEncodeSequenceItem items[7] = {
3402 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3404 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3405 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3406 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3407 DWORD cItem = 1, cSwapped = 0;
3410 if (signedInfo->cSignerInfo)
3412 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3413 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3414 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3415 digestAlgorithmsSet.itemOffset =
3416 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3417 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3418 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3419 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3422 items[cItem].pvStructInfo = &signedInfo->content;
3423 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3425 if (signedInfo->cCertEncoded)
3427 certSet.cItems = signedInfo->cCertEncoded;
3428 certSet.items = signedInfo->rgCertEncoded;
3429 certSet.itemSize = sizeof(CERT_BLOB);
3430 certSet.itemOffset = 0;
3431 certSet.encode = CRYPT_CopyEncodedBlob;
3432 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3433 swapped[cSwapped].pvStructInfo = &certSet;
3434 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3435 items[cItem].pvStructInfo = &swapped[cSwapped];
3436 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3440 if (signedInfo->cCrlEncoded)
3442 crlSet.cItems = signedInfo->cCrlEncoded;
3443 crlSet.items = signedInfo->rgCrlEncoded;
3444 crlSet.itemSize = sizeof(CRL_BLOB);
3445 crlSet.itemOffset = 0;
3446 crlSet.encode = CRYPT_CopyEncodedBlob;
3447 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3448 swapped[cSwapped].pvStructInfo = &crlSet;
3449 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3450 items[cItem].pvStructInfo = &swapped[cSwapped];
3451 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3455 if (ret && signedInfo->cSignerInfo)
3457 signerSet.cItems = signedInfo->cSignerInfo;
3458 signerSet.items = signedInfo->rgSignerInfo;
3459 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3460 signerSet.itemOffset = 0;
3461 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3462 items[cItem].pvStructInfo = &signerSet;
3463 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3467 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3468 items, cItem, 0, NULL, pvData, pcbData);
3473 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3474 LPCSTR lpszStructType)
3476 CryptEncodeObjectExFunc encodeFunc = NULL;
3478 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3479 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3481 SetLastError(ERROR_FILE_NOT_FOUND);
3485 if (!HIWORD(lpszStructType))
3487 switch (LOWORD(lpszStructType))
3489 case LOWORD(X509_CERT):
3490 encodeFunc = CRYPT_AsnEncodeCert;
3492 case LOWORD(X509_CERT_TO_BE_SIGNED):
3493 encodeFunc = CRYPT_AsnEncodeCertInfo;
3495 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3496 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3498 case LOWORD(X509_EXTENSIONS):
3499 encodeFunc = CRYPT_AsnEncodeExtensions;
3501 case LOWORD(X509_NAME_VALUE):
3502 encodeFunc = CRYPT_AsnEncodeNameValue;
3504 case LOWORD(X509_NAME):
3505 encodeFunc = CRYPT_AsnEncodeName;
3507 case LOWORD(X509_PUBLIC_KEY_INFO):
3508 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3510 case LOWORD(X509_AUTHORITY_KEY_ID):
3511 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3513 case LOWORD(X509_ALTERNATE_NAME):
3514 encodeFunc = CRYPT_AsnEncodeAltName;
3516 case LOWORD(X509_BASIC_CONSTRAINTS):
3517 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3519 case LOWORD(X509_BASIC_CONSTRAINTS2):
3520 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3522 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3523 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3525 case LOWORD(X509_UNICODE_NAME):
3526 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3528 case LOWORD(PKCS_CONTENT_INFO):
3529 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3531 case LOWORD(PKCS_ATTRIBUTE):
3532 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3534 case LOWORD(X509_UNICODE_NAME_VALUE):
3535 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3537 case LOWORD(X509_OCTET_STRING):
3538 encodeFunc = CRYPT_AsnEncodeOctets;
3540 case LOWORD(X509_BITS):
3541 case LOWORD(X509_KEY_USAGE):
3542 encodeFunc = CRYPT_AsnEncodeBits;
3544 case LOWORD(X509_INTEGER):
3545 encodeFunc = CRYPT_AsnEncodeInt;
3547 case LOWORD(X509_MULTI_BYTE_INTEGER):
3548 encodeFunc = CRYPT_AsnEncodeInteger;
3550 case LOWORD(X509_MULTI_BYTE_UINT):
3551 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3553 case LOWORD(X509_ENUMERATED):
3554 encodeFunc = CRYPT_AsnEncodeEnumerated;
3556 case LOWORD(X509_CHOICE_OF_TIME):
3557 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3559 case LOWORD(X509_AUTHORITY_KEY_ID2):
3560 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3562 case LOWORD(X509_SEQUENCE_OF_ANY):
3563 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3565 case LOWORD(PKCS_UTC_TIME):
3566 encodeFunc = CRYPT_AsnEncodeUtcTime;
3568 case LOWORD(X509_CRL_DIST_POINTS):
3569 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3571 case LOWORD(X509_ENHANCED_KEY_USAGE):
3572 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3574 case LOWORD(PKCS_ATTRIBUTES):
3575 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3577 case LOWORD(X509_ISSUING_DIST_POINT):
3578 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3580 case LOWORD(X509_NAME_CONSTRAINTS):
3581 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3583 case LOWORD(PKCS7_SIGNER_INFO):
3584 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3588 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3589 encodeFunc = CRYPT_AsnEncodeExtensions;
3590 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3591 encodeFunc = CRYPT_AsnEncodeUtcTime;
3592 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3593 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3594 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3595 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3596 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3597 encodeFunc = CRYPT_AsnEncodeEnumerated;
3598 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3599 encodeFunc = CRYPT_AsnEncodeBits;
3600 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3601 encodeFunc = CRYPT_AsnEncodeOctets;
3602 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3603 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3604 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3605 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3606 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3607 encodeFunc = CRYPT_AsnEncodeAltName;
3608 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3609 encodeFunc = CRYPT_AsnEncodeAltName;
3610 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3611 encodeFunc = CRYPT_AsnEncodeAltName;
3612 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3613 encodeFunc = CRYPT_AsnEncodeAltName;
3614 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3615 encodeFunc = CRYPT_AsnEncodeAltName;
3616 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3617 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3618 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3619 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3620 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3621 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3622 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3623 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3627 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3628 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3630 static HCRYPTOIDFUNCSET set = NULL;
3631 CryptEncodeObjectFunc encodeFunc = NULL;
3634 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3635 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3636 (void **)&encodeFunc, hFunc);
3640 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3641 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3643 static HCRYPTOIDFUNCSET set = NULL;
3644 CryptEncodeObjectExFunc encodeFunc = NULL;
3647 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3648 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3649 (void **)&encodeFunc, hFunc);
3653 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3654 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3657 HCRYPTOIDFUNCADDR hFunc = NULL;
3658 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3659 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3661 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3662 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3665 if (!pbEncoded && !pcbEncoded)
3667 SetLastError(ERROR_INVALID_PARAMETER);
3671 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3674 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3675 debugstr_a(lpszStructType));
3676 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3677 lpszStructType, &hFunc);
3678 if (!pCryptEncodeObject)
3679 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3680 lpszStructType, &hFunc);
3682 if (pCryptEncodeObject)
3683 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3684 pvStructInfo, pbEncoded, pcbEncoded);
3685 else if (pCryptEncodeObjectEx)
3686 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3687 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3689 CryptFreeOIDFunctionAddress(hFunc, 0);
3690 TRACE_(crypt)("returning %d\n", ret);
3694 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3695 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3696 void *pvEncoded, DWORD *pcbEncoded)
3699 HCRYPTOIDFUNCADDR hFunc = NULL;
3700 CryptEncodeObjectExFunc encodeFunc = NULL;
3702 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3703 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3704 pvEncoded, pcbEncoded);
3706 if (!pvEncoded && !pcbEncoded)
3708 SetLastError(ERROR_INVALID_PARAMETER);
3712 SetLastError(NOERROR);
3713 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3714 *(BYTE **)pvEncoded = NULL;
3715 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3718 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3719 debugstr_a(lpszStructType));
3720 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3724 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3725 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3728 CryptEncodeObjectFunc pCryptEncodeObject =
3729 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3731 if (pCryptEncodeObject)
3733 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3735 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3736 pvStructInfo, NULL, pcbEncoded);
3737 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3738 pvEncoded, pcbEncoded, *pcbEncoded)))
3739 ret = pCryptEncodeObject(dwCertEncodingType,
3740 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3744 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3745 pvStructInfo, pvEncoded, pcbEncoded);
3749 CryptFreeOIDFunctionAddress(hFunc, 0);
3750 TRACE_(crypt)("returning %d\n", ret);
3754 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3755 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3757 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3758 NULL, 0, NULL, pInfo, pcbInfo);
3761 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3762 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3763 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3767 static CHAR oid[] = szOID_RSA_RSA;
3769 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3770 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3771 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3773 if (!pszPublicKeyObjId)
3774 pszPublicKeyObjId = oid;
3775 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3779 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3782 LPBYTE pubKey = CryptMemAlloc(keySize);
3786 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3790 DWORD encodedLen = 0;
3792 ret = CryptEncodeObject(dwCertEncodingType,
3793 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3796 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3797 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3800 *pcbInfo = sizeNeeded;
3801 else if (*pcbInfo < sizeNeeded)
3803 SetLastError(ERROR_MORE_DATA);
3804 *pcbInfo = sizeNeeded;
3809 pInfo->Algorithm.pszObjId = (char *)pInfo +
3810 sizeof(CERT_PUBLIC_KEY_INFO);
3811 lstrcpyA(pInfo->Algorithm.pszObjId,
3813 pInfo->Algorithm.Parameters.cbData = 0;
3814 pInfo->Algorithm.Parameters.pbData = NULL;
3815 pInfo->PublicKey.pbData =
3816 (BYTE *)pInfo->Algorithm.pszObjId
3817 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3818 pInfo->PublicKey.cbData = encodedLen;
3819 pInfo->PublicKey.cUnusedBits = 0;
3820 ret = CryptEncodeObject(dwCertEncodingType,
3821 RSA_CSP_PUBLICKEYBLOB, pubKey,
3822 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3826 CryptMemFree(pubKey);
3831 CryptDestroyKey(key);
3836 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3837 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3838 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3840 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3841 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3842 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3844 static HCRYPTOIDFUNCSET set = NULL;
3846 ExportPublicKeyInfoExFunc exportFunc = NULL;
3847 HCRYPTOIDFUNCADDR hFunc = NULL;
3849 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3850 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3851 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3855 SetLastError(ERROR_INVALID_PARAMETER);
3859 if (pszPublicKeyObjId)
3862 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3864 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3865 0, (void **)&exportFunc, &hFunc);
3868 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3869 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3870 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3872 CryptFreeOIDFunctionAddress(hFunc, 0);
3876 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3877 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3879 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3883 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3884 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3885 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3888 DWORD pubKeySize = 0;
3890 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3891 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3893 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3894 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3897 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3901 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3902 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3905 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3907 CryptMemFree(pubKey);
3915 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3916 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3917 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3919 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3920 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3921 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3923 static HCRYPTOIDFUNCSET set = NULL;
3925 ImportPublicKeyInfoExFunc importFunc = NULL;
3926 HCRYPTOIDFUNCADDR hFunc = NULL;
3928 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3929 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3932 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3933 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3934 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3936 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3937 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3940 CryptFreeOIDFunctionAddress(hFunc, 0);