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 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
918 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
919 bytesNeeded = 1 + lenBytes + strLen * 2;
921 *pcbEncoded = bytesNeeded;
924 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
925 pbEncoded, pcbEncoded, bytesNeeded)))
929 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
930 pbEncoded = *(BYTE **)pbEncoded;
931 *pbEncoded++ = ASN_BMPSTRING;
932 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
933 pbEncoded += lenBytes;
934 for (i = 0; i < strLen; i++)
936 *pbEncoded++ = (str[i] & 0xff00) >> 8;
937 *pbEncoded++ = str[i] & 0x00ff;
944 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
945 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
949 LPCWSTR str = (LPCWSTR)value->Value.pbData;
950 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
952 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
954 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
956 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
957 bytesNeeded = 1 + lenBytes + encodedLen;
959 *pcbEncoded = bytesNeeded;
962 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
963 pbEncoded, pcbEncoded, bytesNeeded)))
965 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
966 pbEncoded = *(BYTE **)pbEncoded;
967 *pbEncoded++ = ASN_UTF8STRING;
968 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
969 pbEncoded += lenBytes;
970 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
971 bytesNeeded - lenBytes - 1, NULL, NULL);
977 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
978 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
979 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
985 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
987 switch (value->dwValueType)
989 case CERT_RDN_ANY_TYPE:
990 /* explicitly disallowed */
991 SetLastError(E_INVALIDARG);
994 case CERT_RDN_ENCODED_BLOB:
995 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
996 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
998 case CERT_RDN_OCTET_STRING:
999 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1000 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1002 case CERT_RDN_NUMERIC_STRING:
1003 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1004 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1006 case CERT_RDN_PRINTABLE_STRING:
1007 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1008 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1010 case CERT_RDN_TELETEX_STRING:
1011 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1012 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1014 case CERT_RDN_VIDEOTEX_STRING:
1015 ret = CRYPT_AsnEncodeStringCoerce(value,
1016 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1018 case CERT_RDN_IA5_STRING:
1019 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1020 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1022 case CERT_RDN_GRAPHIC_STRING:
1023 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1024 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1026 case CERT_RDN_VISIBLE_STRING:
1027 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1028 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1030 case CERT_RDN_GENERAL_STRING:
1031 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1032 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1034 case CERT_RDN_UNIVERSAL_STRING:
1035 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1036 SetLastError(CRYPT_E_ASN1_CHOICE);
1039 case CERT_RDN_BMP_STRING:
1040 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1041 pbEncoded, pcbEncoded);
1043 case CERT_RDN_UTF8_STRING:
1044 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1045 pbEncoded, pcbEncoded);
1048 SetLastError(CRYPT_E_ASN1_CHOICE);
1054 SetLastError(STATUS_ACCESS_VIOLATION);
1061 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1062 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1063 BYTE *pbEncoded, DWORD *pcbEncoded)
1065 DWORD bytesNeeded = 0, lenBytes, size;
1068 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1069 0, NULL, NULL, &size);
1072 bytesNeeded += size;
1073 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1074 * with dwValueType, so "cast" it to get its encoded size
1076 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1077 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1080 bytesNeeded += size;
1081 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1082 bytesNeeded += 1 + lenBytes;
1085 if (*pcbEncoded < bytesNeeded)
1087 SetLastError(ERROR_MORE_DATA);
1092 *pbEncoded++ = ASN_SEQUENCE;
1093 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1095 pbEncoded += lenBytes;
1096 size = bytesNeeded - 1 - lenBytes;
1097 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1098 attr->pszObjId, 0, NULL, pbEncoded, &size);
1102 size = bytesNeeded - 1 - lenBytes - size;
1103 ret = nameValueEncodeFunc(dwCertEncodingType,
1104 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1105 0, NULL, pbEncoded, &size);
1112 *pcbEncoded = bytesNeeded;
1116 /* Have to propagate index of failing character */
1123 static int BLOBComp(const void *l, const void *r)
1125 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1128 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1129 ret = a->cbData - b->cbData;
1133 typedef struct _CRYPT_SET_OF {
1135 PCRYPT_DER_BLOB rgValue;
1138 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1140 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1141 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1142 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1144 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1145 DWORD bytesNeeded = 0, lenBytes, i;
1148 for (i = 0; i < set->cValue; i++)
1149 bytesNeeded += set->rgValue[i].cbData;
1150 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1151 bytesNeeded += 1 + lenBytes;
1154 *pcbEncoded = bytesNeeded;
1157 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1158 pbEncoded, pcbEncoded, bytesNeeded)))
1160 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1161 pbEncoded = *(BYTE **)pbEncoded;
1162 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1163 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1164 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1165 pbEncoded += lenBytes;
1166 for (i = 0; ret && i < set->cValue; i++)
1168 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1169 pbEncoded += set->rgValue[i].cbData;
1175 struct DERSetDescriptor
1181 CryptEncodeObjectExFunc encode;
1184 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1185 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1186 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1188 const struct DERSetDescriptor *desc =
1189 (const struct DERSetDescriptor *)pvStructInfo;
1190 CRYPT_SET_OF setOf = { 0, NULL };
1196 setOf.rgValue = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1201 setOf.cValue = desc->cItems;
1202 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1205 for (i = 0; ret && i < setOf.cValue; i++)
1207 ret = desc->encode(dwCertEncodingType, lpszStructType,
1208 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1209 0, NULL, NULL, &setOf.rgValue[i].cbData);
1212 setOf.rgValue[i].pbData = CryptMemAlloc(setOf.rgValue[i].cbData);
1213 if (!setOf.rgValue[i].pbData)
1216 ret = desc->encode(dwCertEncodingType, lpszStructType,
1217 (const BYTE *)desc->items + i * desc->itemSize +
1218 desc->itemOffset, 0, NULL, setOf.rgValue[i].pbData,
1219 &setOf.rgValue[i].cbData);
1221 /* Some functions propagate their errors through the size */
1223 *pcbEncoded = setOf.rgValue[i].cbData;
1227 DWORD bytesNeeded = 0, lenBytes;
1230 for (i = 0; i < setOf.cValue; i++)
1231 bytesNeeded += setOf.rgValue[i].cbData;
1232 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1233 bytesNeeded += 1 + lenBytes;
1235 *pcbEncoded = bytesNeeded;
1236 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1237 pbEncoded, pcbEncoded, bytesNeeded)))
1239 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1240 pbEncoded = *(BYTE **)pbEncoded;
1241 qsort(setOf.rgValue, setOf.cValue, sizeof(CRYPT_DER_BLOB),
1243 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1244 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1245 pbEncoded += lenBytes;
1246 for (i = 0; i < setOf.cValue; i++)
1248 memcpy(pbEncoded, setOf.rgValue[i].pbData,
1249 setOf.rgValue[i].cbData);
1250 pbEncoded += setOf.rgValue[i].cbData;
1254 for (i = 0; i < setOf.cValue; i++)
1255 CryptMemFree(setOf.rgValue[i].pbData);
1256 CryptMemFree(setOf.rgValue);
1260 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1261 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1265 CRYPT_SET_OF setOf = { 0, NULL };
1274 setOf.cValue = rdn->cRDNAttr;
1275 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1276 sizeof(CRYPT_DER_BLOB));
1280 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1282 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1284 setOf.rgValue[i].cbData = 0;
1285 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1286 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1289 setOf.rgValue[i].pbData =
1290 CryptMemAlloc(setOf.rgValue[i].cbData);
1291 if (!setOf.rgValue[i].pbData)
1294 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1295 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1296 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1300 /* Have to propagate index of failing character */
1301 *pcbEncoded = setOf.rgValue[i].cbData;
1305 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1306 pbEncoded, pcbEncoded);
1307 for (i = 0; i < setOf.cValue; i++)
1308 CryptMemFree(setOf.rgValue[i].pbData);
1312 SetLastError(STATUS_ACCESS_VIOLATION);
1316 CryptMemFree(setOf.rgValue);
1320 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1321 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1322 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1324 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1325 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1326 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1329 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1332 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1333 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1334 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1336 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1337 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1341 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1342 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1343 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1349 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1350 DWORD bytesNeeded = 0, lenBytes, size, i;
1352 TRACE("encoding name with %d RDNs\n", info->cRDN);
1354 for (i = 0; ret && i < info->cRDN; i++)
1356 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1357 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1359 bytesNeeded += size;
1363 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1364 bytesNeeded += 1 + lenBytes;
1368 *pcbEncoded = bytesNeeded;
1371 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1372 pbEncoded, pcbEncoded, bytesNeeded)))
1374 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1375 pbEncoded = *(BYTE **)pbEncoded;
1376 *pbEncoded++ = ASN_SEQUENCEOF;
1377 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1379 pbEncoded += lenBytes;
1380 for (i = 0; ret && i < info->cRDN; i++)
1383 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1384 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1389 bytesNeeded -= size;
1400 SetLastError(STATUS_ACCESS_VIOLATION);
1407 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1408 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1409 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1415 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1417 if (!attr->pszObjId)
1418 SetLastError(E_INVALIDARG);
1421 struct AsnEncodeSequenceItem items[2] = {
1422 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1423 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1426 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1427 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1433 SetLastError(STATUS_ACCESS_VIOLATION);
1439 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1440 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1441 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1447 const CRYPT_ATTRIBUTES *attributes =
1448 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1449 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1450 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1452 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1453 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1457 SetLastError(STATUS_ACCESS_VIOLATION);
1463 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1464 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1465 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1466 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1469 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1470 struct AsnEncodeSequenceItem items[2] = {
1471 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1474 struct AsnConstructedItem constructed = { 0 };
1477 if (info->Content.cbData)
1479 constructed.tag = 0;
1480 constructed.pvStructInfo = &info->Content;
1481 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1482 items[cItem].pvStructInfo = &constructed;
1483 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1486 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1487 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1490 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1491 void *pvData, DWORD *pcbData)
1493 struct AsnEncodeSequenceItem items[] = {
1494 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1495 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1497 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1498 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1501 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1502 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1505 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1506 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1507 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1513 const CRYPT_CONTENT_INFO *info =
1514 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1516 if (!info->pszObjId)
1517 SetLastError(E_INVALIDARG);
1519 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1520 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1525 SetLastError(STATUS_ACCESS_VIOLATION);
1531 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1532 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1536 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1537 DWORD bytesNeeded, lenBytes, encodedLen;
1539 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1541 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1542 bytesNeeded = 1 + lenBytes + encodedLen;
1544 *pcbEncoded = bytesNeeded;
1547 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1548 pbEncoded, pcbEncoded, bytesNeeded)))
1552 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1553 pbEncoded = *(BYTE **)pbEncoded;
1555 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1556 pbEncoded += lenBytes;
1557 for (i = 0; i < encodedLen; i++)
1558 *pbEncoded++ = (BYTE)str[i];
1564 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1565 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1569 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1570 DWORD bytesNeeded, lenBytes, encodedLen;
1572 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1574 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1575 bytesNeeded = 1 + lenBytes + encodedLen;
1577 *pcbEncoded = bytesNeeded;
1580 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1581 pbEncoded, pcbEncoded, bytesNeeded)))
1585 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1586 pbEncoded = *(BYTE **)pbEncoded;
1587 *pbEncoded++ = ASN_NUMERICSTRING;
1588 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1589 pbEncoded += lenBytes;
1590 for (i = 0; ret && i < encodedLen; i++)
1592 if (isdigitW(str[i]))
1593 *pbEncoded++ = (BYTE)str[i];
1597 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1606 static inline int isprintableW(WCHAR wc)
1608 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1609 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1610 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1613 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1614 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1618 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1619 DWORD bytesNeeded, lenBytes, encodedLen;
1621 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1623 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1624 bytesNeeded = 1 + lenBytes + encodedLen;
1626 *pcbEncoded = bytesNeeded;
1629 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1630 pbEncoded, pcbEncoded, bytesNeeded)))
1634 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1635 pbEncoded = *(BYTE **)pbEncoded;
1636 *pbEncoded++ = ASN_PRINTABLESTRING;
1637 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1638 pbEncoded += lenBytes;
1639 for (i = 0; ret && i < encodedLen; i++)
1641 if (isprintableW(str[i]))
1642 *pbEncoded++ = (BYTE)str[i];
1646 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1655 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1656 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1660 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1661 DWORD bytesNeeded, lenBytes, encodedLen;
1663 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1665 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1666 bytesNeeded = 1 + lenBytes + encodedLen;
1668 *pcbEncoded = bytesNeeded;
1671 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1672 pbEncoded, pcbEncoded, bytesNeeded)))
1676 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1677 pbEncoded = *(BYTE **)pbEncoded;
1678 *pbEncoded++ = ASN_IA5STRING;
1679 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1680 pbEncoded += lenBytes;
1681 for (i = 0; ret && i < encodedLen; i++)
1684 *pbEncoded++ = (BYTE)str[i];
1688 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1697 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1698 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1702 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1703 DWORD bytesNeeded, lenBytes, strLen;
1705 /* FIXME: doesn't handle composite characters */
1706 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1708 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1709 bytesNeeded = 1 + lenBytes + strLen * 4;
1711 *pcbEncoded = bytesNeeded;
1714 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1715 pbEncoded, pcbEncoded, bytesNeeded)))
1719 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1720 pbEncoded = *(BYTE **)pbEncoded;
1721 *pbEncoded++ = ASN_UNIVERSALSTRING;
1722 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1723 pbEncoded += lenBytes;
1724 for (i = 0; i < strLen; i++)
1728 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1729 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1736 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1737 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1738 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1744 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1746 switch (value->dwValueType)
1748 case CERT_RDN_ANY_TYPE:
1749 case CERT_RDN_ENCODED_BLOB:
1750 case CERT_RDN_OCTET_STRING:
1751 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1753 case CERT_RDN_NUMERIC_STRING:
1754 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1755 pbEncoded, pcbEncoded);
1757 case CERT_RDN_PRINTABLE_STRING:
1758 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1759 pbEncoded, pcbEncoded);
1761 case CERT_RDN_TELETEX_STRING:
1762 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1763 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1765 case CERT_RDN_VIDEOTEX_STRING:
1766 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1767 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1769 case CERT_RDN_IA5_STRING:
1770 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1771 pbEncoded, pcbEncoded);
1773 case CERT_RDN_GRAPHIC_STRING:
1774 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1775 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1777 case CERT_RDN_VISIBLE_STRING:
1778 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1779 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1781 case CERT_RDN_GENERAL_STRING:
1782 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1783 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1785 case CERT_RDN_UNIVERSAL_STRING:
1786 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1787 pbEncoded, pcbEncoded);
1789 case CERT_RDN_BMP_STRING:
1790 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1791 pbEncoded, pcbEncoded);
1793 case CERT_RDN_UTF8_STRING:
1794 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1795 pbEncoded, pcbEncoded);
1798 SetLastError(CRYPT_E_ASN1_CHOICE);
1803 SetLastError(STATUS_ACCESS_VIOLATION);
1809 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1810 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1811 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1817 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1818 DWORD bytesNeeded = 0, lenBytes, size, i;
1820 TRACE("encoding name with %d RDNs\n", info->cRDN);
1822 for (i = 0; ret && i < info->cRDN; i++)
1824 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1825 CRYPT_AsnEncodeNameValue, NULL, &size);
1827 bytesNeeded += size;
1829 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1830 bytesNeeded += 1 + lenBytes;
1834 *pcbEncoded = bytesNeeded;
1837 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1838 pbEncoded, pcbEncoded, bytesNeeded)))
1840 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1841 pbEncoded = *(BYTE **)pbEncoded;
1842 *pbEncoded++ = ASN_SEQUENCEOF;
1843 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1845 pbEncoded += lenBytes;
1846 for (i = 0; ret && i < info->cRDN; i++)
1849 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1850 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1855 bytesNeeded -= size;
1864 SetLastError(STATUS_ACCESS_VIOLATION);
1871 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1872 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1873 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1875 BOOL val = *(const BOOL *)pvStructInfo, ret;
1884 else if (*pcbEncoded < 3)
1887 SetLastError(ERROR_MORE_DATA);
1893 *pbEncoded++ = ASN_BOOL;
1895 *pbEncoded++ = val ? 0xff : 0;
1898 TRACE("returning %d (%08x)\n", ret, GetLastError());
1902 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
1903 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1904 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1906 const CERT_ALT_NAME_ENTRY *entry =
1907 (const CERT_ALT_NAME_ENTRY *)pvStructInfo;
1913 switch (entry->dwAltNameChoice)
1915 case CERT_ALT_NAME_RFC822_NAME:
1916 case CERT_ALT_NAME_DNS_NAME:
1917 case CERT_ALT_NAME_URL:
1918 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1919 if (entry->u.pwszURL)
1923 /* Not + 1: don't encode the NULL-terminator */
1924 dataLen = lstrlenW(entry->u.pwszURL);
1925 for (i = 0; ret && i < dataLen; i++)
1927 if (entry->u.pwszURL[i] > 0x7f)
1929 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1938 case CERT_ALT_NAME_DIRECTORY_NAME:
1939 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
1940 dataLen = entry->u.DirectoryName.cbData;
1942 case CERT_ALT_NAME_IP_ADDRESS:
1943 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1944 dataLen = entry->u.IPAddress.cbData;
1946 case CERT_ALT_NAME_REGISTERED_ID:
1948 struct AsnEncodeTagSwappedItem swapped =
1949 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
1950 CRYPT_AsnEncodeOid };
1952 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
1955 case CERT_ALT_NAME_OTHER_NAME:
1956 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1959 SetLastError(E_INVALIDARG);
1964 DWORD bytesNeeded, lenBytes;
1966 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1967 bytesNeeded = 1 + dataLen + lenBytes;
1969 *pcbEncoded = bytesNeeded;
1970 else if (*pcbEncoded < bytesNeeded)
1972 SetLastError(ERROR_MORE_DATA);
1973 *pcbEncoded = bytesNeeded;
1979 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1980 pbEncoded += lenBytes;
1981 switch (entry->dwAltNameChoice)
1983 case CERT_ALT_NAME_RFC822_NAME:
1984 case CERT_ALT_NAME_DNS_NAME:
1985 case CERT_ALT_NAME_URL:
1989 for (i = 0; i < dataLen; i++)
1990 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1993 case CERT_ALT_NAME_DIRECTORY_NAME:
1994 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
1996 case CERT_ALT_NAME_IP_ADDRESS:
1997 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2001 *pcbEncoded = bytesNeeded;
2004 TRACE("returning %d (%08x)\n", ret, GetLastError());
2008 static BOOL WINAPI CRYPT_AsnEncodeIntegerSwapBytes(DWORD dwCertEncodingType,
2009 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2010 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2016 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2017 CRYPT_DATA_BLOB newBlob = { blob->cbData, NULL };
2022 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2027 for (i = 0; i < newBlob.cbData; i++)
2028 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2034 ret = CRYPT_AsnEncodeInteger(dwCertEncodingType, lpszStructType,
2035 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2036 CryptMemFree(newBlob.pbData);
2040 SetLastError(STATUS_ACCESS_VIOLATION);
2047 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2048 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2049 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2055 const CERT_AUTHORITY_KEY_ID_INFO *info =
2056 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2057 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2058 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2059 struct AsnConstructedItem constructed = { 0 };
2060 DWORD cItem = 0, cSwapped = 0;
2062 if (info->KeyId.cbData)
2064 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2065 swapped[cSwapped].pvStructInfo = &info->KeyId;
2066 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2067 items[cItem].pvStructInfo = &swapped[cSwapped];
2068 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2072 if (info->CertIssuer.cbData)
2074 constructed.tag = 1;
2075 constructed.pvStructInfo = &info->CertIssuer;
2076 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2077 items[cItem].pvStructInfo = &constructed;
2078 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2081 if (info->CertSerialNumber.cbData)
2083 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2084 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2085 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2086 items[cItem].pvStructInfo = &swapped[cSwapped];
2087 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2091 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2092 pEncodePara, pbEncoded, pcbEncoded);
2096 SetLastError(STATUS_ACCESS_VIOLATION);
2103 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2104 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2105 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2111 const CERT_ALT_NAME_INFO *info =
2112 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2113 DWORD bytesNeeded, dataLen, lenBytes, i;
2116 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2117 * can't encode an erroneous entry index if it's bigger than this.
2119 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2123 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2124 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2127 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2129 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2130 * the bad character, now set the index of the bad
2133 *pcbEncoded = (BYTE)i <<
2134 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2139 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2140 bytesNeeded = 1 + lenBytes + dataLen;
2143 *pcbEncoded = bytesNeeded;
2148 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2149 pbEncoded, pcbEncoded, bytesNeeded)))
2151 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2152 pbEncoded = *(BYTE **)pbEncoded;
2153 *pbEncoded++ = ASN_SEQUENCEOF;
2154 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2155 pbEncoded += lenBytes;
2156 for (i = 0; ret && i < info->cAltEntry; i++)
2158 DWORD len = dataLen;
2160 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2161 NULL, &info->rgAltEntry[i], 0, NULL, pbEncoded, &len);
2174 SetLastError(STATUS_ACCESS_VIOLATION);
2181 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2182 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2183 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2189 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2190 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2191 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2192 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2193 DWORD cItem = 0, cSwapped = 0;
2195 if (info->KeyId.cbData)
2197 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2198 swapped[cSwapped].pvStructInfo = &info->KeyId;
2199 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeIntegerSwapBytes;
2200 items[cItem].pvStructInfo = &swapped[cSwapped];
2201 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2205 if (info->AuthorityCertIssuer.cAltEntry)
2207 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2208 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2209 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2210 items[cItem].pvStructInfo = &swapped[cSwapped];
2211 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2215 if (info->AuthorityCertSerialNumber.cbData)
2217 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2218 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2219 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2220 items[cItem].pvStructInfo = &swapped[cSwapped];
2221 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2225 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2226 pEncodePara, pbEncoded, pcbEncoded);
2230 SetLastError(STATUS_ACCESS_VIOLATION);
2237 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2238 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2239 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2245 const CERT_BASIC_CONSTRAINTS_INFO *info =
2246 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2247 struct AsnEncodeSequenceItem items[3] = {
2248 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2253 if (info->fPathLenConstraint)
2255 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2256 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2259 if (info->cSubtreesConstraint)
2261 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2262 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2265 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2266 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2270 SetLastError(STATUS_ACCESS_VIOLATION);
2277 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2278 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2279 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2285 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2286 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2287 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2292 items[cItem].pvStructInfo = &info->fCA;
2293 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2296 if (info->fPathLenConstraint)
2298 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2299 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2302 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2303 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2307 SetLastError(STATUS_ACCESS_VIOLATION);
2314 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2315 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2316 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2322 const BLOBHEADER *hdr =
2323 (const BLOBHEADER *)pvStructInfo;
2325 if (hdr->bType != PUBLICKEYBLOB)
2327 SetLastError(E_INVALIDARG);
2332 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2333 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2334 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2335 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2336 struct AsnEncodeSequenceItem items[] = {
2337 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2338 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2341 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2342 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2348 SetLastError(STATUS_ACCESS_VIOLATION);
2355 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2356 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2357 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2363 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2364 DWORD bytesNeeded, lenBytes;
2366 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2367 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2369 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2370 bytesNeeded = 1 + lenBytes + blob->cbData;
2373 *pcbEncoded = bytesNeeded;
2378 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2379 pcbEncoded, bytesNeeded)))
2381 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2382 pbEncoded = *(BYTE **)pbEncoded;
2383 *pbEncoded++ = ASN_OCTETSTRING;
2384 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2385 pbEncoded += lenBytes;
2387 memcpy(pbEncoded, blob->pbData, blob->cbData);
2393 SetLastError(STATUS_ACCESS_VIOLATION);
2397 TRACE("returning %d (%08x)\n", ret, GetLastError());
2401 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2409 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2410 DWORD bytesNeeded, lenBytes, dataBytes;
2413 /* yep, MS allows cUnusedBits to be >= 8 */
2414 if (!blob->cUnusedBits)
2416 dataBytes = blob->cbData;
2419 else if (blob->cbData * 8 > blob->cUnusedBits)
2421 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2422 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2430 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2431 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2434 *pcbEncoded = bytesNeeded;
2439 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2440 pcbEncoded, bytesNeeded)))
2442 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2443 pbEncoded = *(BYTE **)pbEncoded;
2444 *pbEncoded++ = ASN_BITSTRING;
2445 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2446 pbEncoded += lenBytes;
2447 *pbEncoded++ = unusedBits;
2450 BYTE mask = 0xff << unusedBits;
2454 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2455 pbEncoded += dataBytes - 1;
2457 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2464 SetLastError(STATUS_ACCESS_VIOLATION);
2471 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2479 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2480 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2485 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2490 for (i = 0; i < newBlob.cbData; i++)
2491 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2497 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2498 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2499 CryptMemFree(newBlob.pbData);
2503 SetLastError(STATUS_ACCESS_VIOLATION);
2510 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2511 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2512 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2514 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2516 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2517 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2520 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2521 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2522 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2528 DWORD significantBytes, lenBytes;
2529 BYTE padByte = 0, bytesNeeded;
2531 const CRYPT_INTEGER_BLOB *blob =
2532 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2534 significantBytes = blob->cbData;
2535 if (significantBytes)
2537 if (blob->pbData[significantBytes - 1] & 0x80)
2539 /* negative, lop off leading (little-endian) 0xffs */
2540 for (; significantBytes > 0 &&
2541 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2543 if (blob->pbData[significantBytes - 1] < 0x80)
2551 /* positive, lop off leading (little-endian) zeroes */
2552 for (; significantBytes > 0 &&
2553 !blob->pbData[significantBytes - 1]; significantBytes--)
2555 if (significantBytes == 0)
2556 significantBytes = 1;
2557 if (blob->pbData[significantBytes - 1] > 0x7f)
2565 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2567 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2568 bytesNeeded = 1 + lenBytes + significantBytes;
2573 *pcbEncoded = bytesNeeded;
2578 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2579 pcbEncoded, bytesNeeded)))
2581 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2582 pbEncoded = *(BYTE **)pbEncoded;
2583 *pbEncoded++ = ASN_INTEGER;
2586 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2587 pbEncoded += lenBytes;
2588 *pbEncoded++ = padByte;
2592 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2593 pbEncoded += lenBytes;
2595 for (; significantBytes > 0; significantBytes--)
2596 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2602 SetLastError(STATUS_ACCESS_VIOLATION);
2609 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2610 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2611 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2617 DWORD significantBytes, lenBytes;
2620 const CRYPT_INTEGER_BLOB *blob =
2621 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2623 significantBytes = blob->cbData;
2624 if (significantBytes)
2626 /* positive, lop off leading (little-endian) zeroes */
2627 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2630 if (significantBytes == 0)
2631 significantBytes = 1;
2632 if (blob->pbData[significantBytes - 1] > 0x7f)
2636 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2638 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2639 bytesNeeded = 1 + lenBytes + significantBytes;
2644 *pcbEncoded = bytesNeeded;
2649 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2650 pcbEncoded, bytesNeeded)))
2652 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2653 pbEncoded = *(BYTE **)pbEncoded;
2654 *pbEncoded++ = ASN_INTEGER;
2657 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2658 pbEncoded += lenBytes;
2663 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2664 pbEncoded += lenBytes;
2666 for (; significantBytes > 0; significantBytes--)
2667 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2673 SetLastError(STATUS_ACCESS_VIOLATION);
2680 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2681 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2682 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2684 CRYPT_INTEGER_BLOB blob;
2687 /* Encode as an unsigned integer, then change the tag to enumerated */
2688 blob.cbData = sizeof(DWORD);
2689 blob.pbData = (BYTE *)pvStructInfo;
2690 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2691 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2692 if (ret && pbEncoded)
2694 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2695 pbEncoded = *(BYTE **)pbEncoded;
2696 pbEncoded[0] = ASN_ENUMERATED;
2701 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2702 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2703 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2710 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2711 * temporary buffer because the output buffer is not NULL-terminated.
2714 static const DWORD bytesNeeded = sizeof(buf) - 1;
2718 *pcbEncoded = bytesNeeded;
2723 /* Sanity check the year, this is a two-digit year format */
2724 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2726 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2728 SetLastError(CRYPT_E_BAD_ENCODE);
2733 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2734 pbEncoded, pcbEncoded, bytesNeeded)))
2736 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2737 pbEncoded = *(BYTE **)pbEncoded;
2738 buf[0] = ASN_UTCTIME;
2739 buf[1] = bytesNeeded - 2;
2740 snprintf(buf + 2, sizeof(buf) - 2,
2741 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2742 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2743 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2744 sysTime.wMinute, sysTime.wSecond);
2745 memcpy(pbEncoded, buf, bytesNeeded);
2752 SetLastError(STATUS_ACCESS_VIOLATION);
2759 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2760 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2761 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2768 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2769 * temporary buffer because the output buffer is not NULL-terminated.
2772 static const DWORD bytesNeeded = sizeof(buf) - 1;
2776 *pcbEncoded = bytesNeeded;
2781 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2784 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2785 pcbEncoded, bytesNeeded);
2788 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2789 pbEncoded = *(BYTE **)pbEncoded;
2790 buf[0] = ASN_GENERALTIME;
2791 buf[1] = bytesNeeded - 2;
2792 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2793 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2794 sysTime.wMinute, sysTime.wSecond);
2795 memcpy(pbEncoded, buf, bytesNeeded);
2801 SetLastError(STATUS_ACCESS_VIOLATION);
2808 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2809 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2810 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2818 /* Check the year, if it's in the UTCTime range call that encode func */
2819 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2821 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2822 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2823 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2825 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2826 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2831 SetLastError(STATUS_ACCESS_VIOLATION);
2838 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2839 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2840 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2846 DWORD bytesNeeded, dataLen, lenBytes, i;
2847 const CRYPT_SEQUENCE_OF_ANY *seq =
2848 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2850 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2851 dataLen += seq->rgValue[i].cbData;
2852 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2853 bytesNeeded = 1 + lenBytes + dataLen;
2856 *pcbEncoded = bytesNeeded;
2861 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2862 pcbEncoded, bytesNeeded)))
2864 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2865 pbEncoded = *(BYTE **)pbEncoded;
2866 *pbEncoded++ = ASN_SEQUENCEOF;
2867 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2868 pbEncoded += lenBytes;
2869 for (i = 0; i < seq->cValue; i++)
2871 memcpy(pbEncoded, seq->rgValue[i].pbData,
2872 seq->rgValue[i].cbData);
2873 pbEncoded += seq->rgValue[i].cbData;
2880 SetLastError(STATUS_ACCESS_VIOLATION);
2887 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2888 BYTE *pbEncoded, DWORD *pcbEncoded)
2891 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2892 struct AsnConstructedItem constructed = { 0 };
2893 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2894 DWORD cItem = 0, cSwapped = 0;
2896 switch (distPoint->DistPointName.dwDistPointNameChoice)
2898 case CRL_DIST_POINT_NO_NAME:
2901 case CRL_DIST_POINT_FULL_NAME:
2902 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2903 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2904 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2905 constructed.tag = 0;
2906 constructed.pvStructInfo = &swapped[cSwapped];
2907 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2908 items[cItem].pvStructInfo = &constructed;
2909 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2913 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2914 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2920 if (ret && distPoint->ReasonFlags.cbData)
2922 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2923 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2924 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2925 items[cItem].pvStructInfo = &swapped[cSwapped];
2926 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2930 if (ret && distPoint->CRLIssuer.cAltEntry)
2932 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2933 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2934 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2935 items[cItem].pvStructInfo = &swapped[cSwapped];
2936 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2941 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2942 pbEncoded, pcbEncoded);
2946 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2947 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2948 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2954 const CRL_DIST_POINTS_INFO *info =
2955 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2957 if (!info->cDistPoint)
2959 SetLastError(E_INVALIDARG);
2964 DWORD bytesNeeded, dataLen, lenBytes, i;
2967 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2971 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2975 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2977 /* Have to propagate index of failing character */
2983 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2984 bytesNeeded = 1 + lenBytes + dataLen;
2987 *pcbEncoded = bytesNeeded;
2992 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2993 pbEncoded, pcbEncoded, bytesNeeded)))
2995 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2996 pbEncoded = *(BYTE **)pbEncoded;
2997 *pbEncoded++ = ASN_SEQUENCEOF;
2998 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2999 pbEncoded += lenBytes;
3000 for (i = 0; ret && i < info->cDistPoint; i++)
3002 DWORD len = dataLen;
3004 ret = CRYPT_AsnEncodeDistPoint(
3005 &info->rgDistPoint[i], pbEncoded, &len);
3019 SetLastError(STATUS_ACCESS_VIOLATION);
3026 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3027 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3028 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3034 const CERT_ENHKEY_USAGE *usage =
3035 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3036 DWORD bytesNeeded = 0, lenBytes, size, i;
3039 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3041 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3042 usage->rgpszUsageIdentifier[i],
3043 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3045 bytesNeeded += size;
3047 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3048 bytesNeeded += 1 + lenBytes;
3052 *pcbEncoded = bytesNeeded;
3055 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3056 pbEncoded, pcbEncoded, bytesNeeded)))
3058 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3059 pbEncoded = *(BYTE **)pbEncoded;
3060 *pbEncoded++ = ASN_SEQUENCEOF;
3061 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3063 pbEncoded += lenBytes;
3064 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3067 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3068 usage->rgpszUsageIdentifier[i],
3069 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3074 bytesNeeded -= size;
3083 SetLastError(STATUS_ACCESS_VIOLATION);
3090 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3091 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3092 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3098 const CRL_ISSUING_DIST_POINT *point =
3099 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3100 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3101 struct AsnConstructedItem constructed = { 0 };
3102 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3103 DWORD cItem = 0, cSwapped = 0;
3106 switch (point->DistPointName.dwDistPointNameChoice)
3108 case CRL_DIST_POINT_NO_NAME:
3111 case CRL_DIST_POINT_FULL_NAME:
3112 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3113 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3114 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3115 constructed.tag = 0;
3116 constructed.pvStructInfo = &swapped[cSwapped];
3117 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3118 items[cItem].pvStructInfo = &constructed;
3119 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3124 SetLastError(E_INVALIDARG);
3127 if (ret && point->fOnlyContainsUserCerts)
3129 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3130 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3131 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3132 items[cItem].pvStructInfo = &swapped[cSwapped];
3133 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3137 if (ret && point->fOnlyContainsCACerts)
3139 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3140 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3141 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3142 items[cItem].pvStructInfo = &swapped[cSwapped];
3143 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3147 if (ret && point->OnlySomeReasonFlags.cbData)
3149 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3150 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3151 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3152 items[cItem].pvStructInfo = &swapped[cSwapped];
3153 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3157 if (ret && point->fIndirectCRL)
3159 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3160 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3161 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3162 items[cItem].pvStructInfo = &swapped[cSwapped];
3163 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3168 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3169 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3173 SetLastError(STATUS_ACCESS_VIOLATION);
3180 static BOOL WINAPI CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3181 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3185 const CERT_GENERAL_SUBTREE *subtree =
3186 (const CERT_GENERAL_SUBTREE *)pvStructInfo;
3187 struct AsnEncodeSequenceItem items[3] = {
3188 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3191 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3192 DWORD cItem = 1, cSwapped = 0;
3194 if (subtree->dwMinimum)
3196 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3197 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
3198 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3199 items[cItem].pvStructInfo = &swapped[cSwapped];
3200 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3204 if (subtree->fMaximum)
3206 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3207 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
3208 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3209 items[cItem].pvStructInfo = &swapped[cSwapped];
3210 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3214 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
3215 pEncodePara, pbEncoded, pcbEncoded);
3219 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
3220 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3221 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3224 CRYPT_SET_OF permitted = { 0, NULL }, excluded = { 0, NULL };
3226 TRACE("%p\n", pvStructInfo);
3230 const CERT_NAME_CONSTRAINTS_INFO *constraints =
3231 (const CERT_NAME_CONSTRAINTS_INFO *)pvStructInfo;
3232 struct AsnEncodeSequenceItem items[2] = { { 0 } };
3233 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3234 DWORD i, cItem = 0, cSwapped = 0;
3237 if (constraints->cPermittedSubtree)
3239 permitted.rgValue = CryptMemAlloc(
3240 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
3241 if (permitted.rgValue)
3243 permitted.cValue = constraints->cPermittedSubtree;
3244 memset(permitted.rgValue, 0,
3245 permitted.cValue * sizeof(CRYPT_DER_BLOB));
3246 for (i = 0; ret && i < permitted.cValue; i++)
3247 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3248 NULL, &constraints->rgPermittedSubtree[i],
3249 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3250 (BYTE *)&permitted.rgValue[i].pbData,
3251 &permitted.rgValue[i].cbData);
3254 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3255 swapped[cSwapped].pvStructInfo = &permitted;
3256 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3257 items[cItem].pvStructInfo = &swapped[cSwapped];
3258 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3266 if (constraints->cExcludedSubtree)
3268 excluded.rgValue = CryptMemAlloc(
3269 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
3270 if (excluded.rgValue)
3272 excluded.cValue = constraints->cExcludedSubtree;
3273 memset(excluded.rgValue, 0,
3274 excluded.cValue * sizeof(CRYPT_DER_BLOB));
3275 for (i = 0; ret && i < excluded.cValue; i++)
3276 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
3277 NULL, &constraints->rgExcludedSubtree[i],
3278 CRYPT_ENCODE_ALLOC_FLAG, NULL,
3279 (BYTE *)&excluded.rgValue[i].pbData,
3280 &excluded.rgValue[i].cbData);
3283 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3284 swapped[cSwapped].pvStructInfo = &excluded;
3285 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
3286 items[cItem].pvStructInfo = &swapped[cSwapped];
3287 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3296 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3297 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3298 for (i = 0; i < permitted.cValue; i++)
3299 LocalFree(permitted.rgValue[i].pbData);
3300 for (i = 0; i < excluded.cValue; i++)
3301 LocalFree(excluded.rgValue[i].pbData);
3305 SetLastError(STATUS_ACCESS_VIOLATION);
3308 CryptMemFree(permitted.rgValue);
3309 CryptMemFree(excluded.rgValue);
3310 TRACE("returning %d\n", ret);
3314 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3315 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3316 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3320 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3321 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3322 struct AsnEncodeSequenceItem items[] = {
3323 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3324 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3327 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3328 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3333 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3334 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3335 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3339 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3341 SetLastError(E_INVALIDARG);
3347 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3349 if (!info->Issuer.cbData)
3350 SetLastError(E_INVALIDARG);
3353 struct AsnEncodeSequenceItem items[7] = {
3354 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3355 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3356 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3359 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3360 DWORD cItem = 3, cSwapped = 0;
3362 if (info->AuthAttrs.cAttr)
3364 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3365 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
3366 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3367 items[cItem].pvStructInfo = &swapped[cSwapped];
3368 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3372 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
3373 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3375 items[cItem].pvStructInfo = &info->EncryptedHash;
3376 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3378 if (info->UnauthAttrs.cAttr)
3380 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
3381 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
3382 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3383 items[cItem].pvStructInfo = &swapped[cSwapped];
3384 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3388 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3389 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3394 SetLastError(STATUS_ACCESS_VIOLATION);
3400 BOOL CRYPT_AsnEncodePKCSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
3403 struct AsnEncodeSequenceItem items[7] = {
3404 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
3406 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
3407 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
3408 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3409 DWORD cItem = 1, cSwapped = 0;
3412 if (signedInfo->cSignerInfo)
3414 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
3415 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
3416 digestAlgorithmsSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3417 digestAlgorithmsSet.itemOffset =
3418 offsetof(CMSG_SIGNER_INFO, HashAlgorithm);
3419 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
3420 items[cItem].pvStructInfo = &digestAlgorithmsSet;
3421 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3424 items[cItem].pvStructInfo = &signedInfo->content;
3425 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
3427 if (signedInfo->cCertEncoded)
3429 certSet.cItems = signedInfo->cCertEncoded;
3430 certSet.items = signedInfo->rgCertEncoded;
3431 certSet.itemSize = sizeof(CERT_BLOB);
3432 certSet.itemOffset = 0;
3433 certSet.encode = CRYPT_CopyEncodedBlob;
3434 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
3435 swapped[cSwapped].pvStructInfo = &certSet;
3436 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3437 items[cItem].pvStructInfo = &swapped[cSwapped];
3438 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3442 if (signedInfo->cCrlEncoded)
3444 crlSet.cItems = signedInfo->cCrlEncoded;
3445 crlSet.items = signedInfo->rgCrlEncoded;
3446 crlSet.itemSize = sizeof(CRL_BLOB);
3447 crlSet.itemOffset = 0;
3448 crlSet.encode = CRYPT_CopyEncodedBlob;
3449 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
3450 swapped[cSwapped].pvStructInfo = &crlSet;
3451 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3452 items[cItem].pvStructInfo = &swapped[cSwapped];
3453 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3457 if (ret && signedInfo->cSignerInfo)
3459 signerSet.cItems = signedInfo->cSignerInfo;
3460 signerSet.items = signedInfo->rgSignerInfo;
3461 signerSet.itemSize = sizeof(CMSG_SIGNER_INFO);
3462 signerSet.itemOffset = 0;
3463 signerSet.encode = CRYPT_AsnEncodePKCSSignerInfo;
3464 items[cItem].pvStructInfo = &signerSet;
3465 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
3469 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
3470 items, cItem, 0, NULL, pvData, pcbData);
3475 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
3476 LPCSTR lpszStructType)
3478 CryptEncodeObjectExFunc encodeFunc = NULL;
3480 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3481 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3483 SetLastError(ERROR_FILE_NOT_FOUND);
3487 if (!HIWORD(lpszStructType))
3489 switch (LOWORD(lpszStructType))
3491 case LOWORD(X509_CERT):
3492 encodeFunc = CRYPT_AsnEncodeCert;
3494 case LOWORD(X509_CERT_TO_BE_SIGNED):
3495 encodeFunc = CRYPT_AsnEncodeCertInfo;
3497 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
3498 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3500 case LOWORD(X509_EXTENSIONS):
3501 encodeFunc = CRYPT_AsnEncodeExtensions;
3503 case LOWORD(X509_NAME_VALUE):
3504 encodeFunc = CRYPT_AsnEncodeNameValue;
3506 case LOWORD(X509_NAME):
3507 encodeFunc = CRYPT_AsnEncodeName;
3509 case LOWORD(X509_PUBLIC_KEY_INFO):
3510 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3512 case LOWORD(X509_AUTHORITY_KEY_ID):
3513 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3515 case LOWORD(X509_ALTERNATE_NAME):
3516 encodeFunc = CRYPT_AsnEncodeAltName;
3518 case LOWORD(X509_BASIC_CONSTRAINTS):
3519 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3521 case LOWORD(X509_BASIC_CONSTRAINTS2):
3522 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3524 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
3525 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3527 case LOWORD(X509_UNICODE_NAME):
3528 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3530 case LOWORD(PKCS_CONTENT_INFO):
3531 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3533 case LOWORD(PKCS_ATTRIBUTE):
3534 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3536 case LOWORD(X509_UNICODE_NAME_VALUE):
3537 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3539 case LOWORD(X509_OCTET_STRING):
3540 encodeFunc = CRYPT_AsnEncodeOctets;
3542 case LOWORD(X509_BITS):
3543 case LOWORD(X509_KEY_USAGE):
3544 encodeFunc = CRYPT_AsnEncodeBits;
3546 case LOWORD(X509_INTEGER):
3547 encodeFunc = CRYPT_AsnEncodeInt;
3549 case LOWORD(X509_MULTI_BYTE_INTEGER):
3550 encodeFunc = CRYPT_AsnEncodeInteger;
3552 case LOWORD(X509_MULTI_BYTE_UINT):
3553 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3555 case LOWORD(X509_ENUMERATED):
3556 encodeFunc = CRYPT_AsnEncodeEnumerated;
3558 case LOWORD(X509_CHOICE_OF_TIME):
3559 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3561 case LOWORD(X509_AUTHORITY_KEY_ID2):
3562 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3564 case LOWORD(X509_SEQUENCE_OF_ANY):
3565 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3567 case LOWORD(PKCS_UTC_TIME):
3568 encodeFunc = CRYPT_AsnEncodeUtcTime;
3570 case LOWORD(X509_CRL_DIST_POINTS):
3571 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3573 case LOWORD(X509_ENHANCED_KEY_USAGE):
3574 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3576 case LOWORD(PKCS_ATTRIBUTES):
3577 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3579 case LOWORD(X509_ISSUING_DIST_POINT):
3580 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3582 case LOWORD(X509_NAME_CONSTRAINTS):
3583 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3585 case LOWORD(PKCS7_SIGNER_INFO):
3586 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3590 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3591 encodeFunc = CRYPT_AsnEncodeExtensions;
3592 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3593 encodeFunc = CRYPT_AsnEncodeUtcTime;
3594 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3595 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3596 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3597 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3598 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3599 encodeFunc = CRYPT_AsnEncodeEnumerated;
3600 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3601 encodeFunc = CRYPT_AsnEncodeBits;
3602 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3603 encodeFunc = CRYPT_AsnEncodeOctets;
3604 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3605 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3606 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3607 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3608 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3609 encodeFunc = CRYPT_AsnEncodeAltName;
3610 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3611 encodeFunc = CRYPT_AsnEncodeAltName;
3612 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3613 encodeFunc = CRYPT_AsnEncodeAltName;
3614 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3615 encodeFunc = CRYPT_AsnEncodeAltName;
3616 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3617 encodeFunc = CRYPT_AsnEncodeAltName;
3618 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3619 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3620 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3621 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3622 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3623 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3624 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
3625 encodeFunc = CRYPT_AsnEncodeNameConstraints;
3629 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
3630 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3632 static HCRYPTOIDFUNCSET set = NULL;
3633 CryptEncodeObjectFunc encodeFunc = NULL;
3636 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
3637 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3638 (void **)&encodeFunc, hFunc);
3642 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
3643 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
3645 static HCRYPTOIDFUNCSET set = NULL;
3646 CryptEncodeObjectExFunc encodeFunc = NULL;
3649 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3650 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3651 (void **)&encodeFunc, hFunc);
3655 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3656 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
3659 HCRYPTOIDFUNCADDR hFunc = NULL;
3660 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
3661 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
3663 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
3664 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
3667 if (!pbEncoded && !pcbEncoded)
3669 SetLastError(ERROR_INVALID_PARAMETER);
3673 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
3676 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3677 debugstr_a(lpszStructType));
3678 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
3679 lpszStructType, &hFunc);
3680 if (!pCryptEncodeObject)
3681 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
3682 lpszStructType, &hFunc);
3684 if (pCryptEncodeObject)
3685 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3686 pvStructInfo, pbEncoded, pcbEncoded);
3687 else if (pCryptEncodeObjectEx)
3688 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
3689 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
3691 CryptFreeOIDFunctionAddress(hFunc, 0);
3692 TRACE_(crypt)("returning %d\n", ret);
3696 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3697 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3698 void *pvEncoded, DWORD *pcbEncoded)
3701 HCRYPTOIDFUNCADDR hFunc = NULL;
3702 CryptEncodeObjectExFunc encodeFunc = NULL;
3704 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3705 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3706 pvEncoded, pcbEncoded);
3708 if (!pvEncoded && !pcbEncoded)
3710 SetLastError(ERROR_INVALID_PARAMETER);
3714 SetLastError(NOERROR);
3715 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3716 *(BYTE **)pvEncoded = NULL;
3717 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
3720 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
3721 debugstr_a(lpszStructType));
3722 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
3726 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3727 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3730 CryptEncodeObjectFunc pCryptEncodeObject =
3731 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
3733 if (pCryptEncodeObject)
3735 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3737 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3738 pvStructInfo, NULL, pcbEncoded);
3739 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3740 pvEncoded, pcbEncoded, *pcbEncoded)))
3741 ret = pCryptEncodeObject(dwCertEncodingType,
3742 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
3746 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
3747 pvStructInfo, pvEncoded, pcbEncoded);
3751 CryptFreeOIDFunctionAddress(hFunc, 0);
3752 TRACE_(crypt)("returning %d\n", ret);
3756 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3757 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3759 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3760 NULL, 0, NULL, pInfo, pcbInfo);
3763 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3764 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3765 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3769 static CHAR oid[] = szOID_RSA_RSA;
3771 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3772 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3773 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3775 if (!pszPublicKeyObjId)
3776 pszPublicKeyObjId = oid;
3777 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3781 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3784 LPBYTE pubKey = CryptMemAlloc(keySize);
3788 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3792 DWORD encodedLen = 0;
3794 ret = CryptEncodeObject(dwCertEncodingType,
3795 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3798 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3799 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3802 *pcbInfo = sizeNeeded;
3803 else if (*pcbInfo < sizeNeeded)
3805 SetLastError(ERROR_MORE_DATA);
3806 *pcbInfo = sizeNeeded;
3811 pInfo->Algorithm.pszObjId = (char *)pInfo +
3812 sizeof(CERT_PUBLIC_KEY_INFO);
3813 lstrcpyA(pInfo->Algorithm.pszObjId,
3815 pInfo->Algorithm.Parameters.cbData = 0;
3816 pInfo->Algorithm.Parameters.pbData = NULL;
3817 pInfo->PublicKey.pbData =
3818 (BYTE *)pInfo->Algorithm.pszObjId
3819 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3820 pInfo->PublicKey.cbData = encodedLen;
3821 pInfo->PublicKey.cUnusedBits = 0;
3822 ret = CryptEncodeObject(dwCertEncodingType,
3823 RSA_CSP_PUBLICKEYBLOB, pubKey,
3824 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3828 CryptMemFree(pubKey);
3833 CryptDestroyKey(key);
3838 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
3839 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3840 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3842 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
3843 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3844 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3846 static HCRYPTOIDFUNCSET set = NULL;
3848 ExportPublicKeyInfoExFunc exportFunc = NULL;
3849 HCRYPTOIDFUNCADDR hFunc = NULL;
3851 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
3852 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
3853 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
3857 SetLastError(ERROR_INVALID_PARAMETER);
3861 if (pszPublicKeyObjId)
3864 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3866 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3867 0, (void **)&exportFunc, &hFunc);
3870 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3871 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3872 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3874 CryptFreeOIDFunctionAddress(hFunc, 0);
3878 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3879 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3881 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3885 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3886 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3887 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3890 DWORD pubKeySize = 0;
3892 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3893 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3895 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3896 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3899 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3903 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3904 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3907 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3909 CryptMemFree(pubKey);
3917 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3918 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3919 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3921 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3922 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3923 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3925 static HCRYPTOIDFUNCSET set = NULL;
3927 ImportPublicKeyInfoExFunc importFunc = NULL;
3928 HCRYPTOIDFUNCADDR hFunc = NULL;
3930 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
3931 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3934 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3935 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3936 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3938 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3939 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3942 CryptFreeOIDFunctionAddress(hFunc, 0);