2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
34 #include "wine/port.h"
41 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "wine/unicode.h"
50 #include "crypt32_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
58 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
59 * The dwCertEncodingType and lpszStructType are ignored by the built-in
60 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
61 * since it must call functions in external DLLs that follow these signatures.
63 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
93 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
95 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
96 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
98 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
100 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
101 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara,
104 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
108 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
110 if (pEncodePara && pEncodePara->pfnAlloc)
111 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
113 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
114 if (!*(BYTE **)pbEncoded)
117 *pcbEncoded = bytesNeeded;
119 else if (bytesNeeded > *pcbEncoded)
121 *pcbEncoded = bytesNeeded;
122 SetLastError(ERROR_MORE_DATA);
126 *pcbEncoded = bytesNeeded;
130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
132 if (pEncodePara && pEncodePara->pfnFree)
133 pEncodePara->pfnFree(pv);
138 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
140 DWORD bytesNeeded, significantBytes = 0;
148 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
149 temp <<= 8, significantBytes--)
151 bytesNeeded = significantBytes + 1;
155 *pcbEncoded = bytesNeeded;
158 if (*pcbEncoded < bytesNeeded)
160 SetLastError(ERROR_MORE_DATA);
164 *pbEncoded = (BYTE)len;
169 *pbEncoded++ = significantBytes | 0x80;
170 for (i = 0; i < significantBytes; i++)
172 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
176 *pcbEncoded = bytesNeeded;
180 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
181 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
185 DWORD i, dataLen = 0;
187 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
188 pbEncoded, *pcbEncoded);
189 for (i = 0, ret = TRUE; ret && i < cItem; i++)
191 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
192 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
193 NULL, &items[i].size);
194 /* Some functions propagate their errors through the size */
196 *pcbEncoded = items[i].size;
197 dataLen += items[i].size;
201 DWORD lenBytes, bytesNeeded;
203 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
204 bytesNeeded = 1 + lenBytes + dataLen;
206 *pcbEncoded = bytesNeeded;
209 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
210 pcbEncoded, bytesNeeded)))
214 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
215 pbEncoded = *(BYTE **)pbEncoded;
217 *out++ = ASN_SEQUENCE;
218 CRYPT_EncodeLen(dataLen, out, &lenBytes);
220 for (i = 0; ret && i < cItem; i++)
222 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
223 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
224 NULL, out, &items[i].size);
225 /* Some functions propagate their errors through the size */
227 *pcbEncoded = items[i].size;
228 out += items[i].size;
230 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
231 CRYPT_FreeSpace(pEncodePara, pbEncoded);
235 TRACE("returning %d (%08x)\n", ret, GetLastError());
239 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
240 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
241 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
244 const struct AsnConstructedItem *item = pvStructInfo;
247 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
248 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
250 DWORD dataLen, bytesNeeded;
252 CRYPT_EncodeLen(len, NULL, &dataLen);
253 bytesNeeded = 1 + dataLen + len;
255 *pcbEncoded = bytesNeeded;
256 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
257 pbEncoded, pcbEncoded, bytesNeeded)))
261 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
262 pbEncoded = *(BYTE **)pbEncoded;
264 *out++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
265 CRYPT_EncodeLen(len, out, &dataLen);
267 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
268 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
272 /* Some functions propagate their errors through the size */
274 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
275 CRYPT_FreeSpace(pEncodePara, pbEncoded);
281 /* Some functions propagate their errors through the size */
287 struct AsnEncodeTagSwappedItem
290 const void *pvStructInfo;
291 CryptEncodeObjectExFunc encodeFunc;
294 /* Sort of a wacky hack, it encodes something using the struct
295 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
296 * given in the struct AsnEncodeTagSwappedItem.
298 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
299 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
300 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
303 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
305 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
306 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
307 if (ret && pbEncoded)
308 *pbEncoded = item->tag;
312 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
313 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
314 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
316 const DWORD *ver = pvStructInfo;
319 /* CERT_V1 is not encoded */
327 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
329 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
330 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
335 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
336 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
337 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
339 const CRYPT_DER_BLOB *blob = pvStructInfo;
344 *pcbEncoded = blob->cbData;
349 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
350 pcbEncoded, blob->cbData)))
352 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
353 pbEncoded = *(BYTE **)pbEncoded;
355 memcpy(pbEncoded, blob->pbData, blob->cbData);
356 *pcbEncoded = blob->cbData;
362 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
363 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
364 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
367 /* This has two filetimes in a row, a NotBefore and a NotAfter */
368 const FILETIME *timePtr = pvStructInfo;
369 struct AsnEncodeSequenceItem items[] = {
370 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
371 { timePtr + 1, CRYPT_AsnEncodeChoiceOfTime, 0 },
374 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
375 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
383 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
384 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
385 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
388 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
389 static const BYTE asn1Null[] = { ASN_NULL, 0 };
390 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
393 struct AsnEncodeSequenceItem items[2] = {
394 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
395 { NULL, CRYPT_CopyEncodedBlob, 0 },
398 if (algo->Parameters.cbData)
399 items[1].pvStructInfo = &algo->Parameters;
401 items[1].pvStructInfo = &nullBlob;
402 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
403 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
408 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
412 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
414 struct AsnEncodeSequenceItem items[] = {
415 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
416 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
419 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
420 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
425 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
426 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
427 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
433 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
434 struct AsnEncodeSequenceItem items[] = {
435 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
436 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
439 TRACE("Encoding public key with OID %s\n",
440 debugstr_a(info->Algorithm.pszObjId));
441 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
442 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
447 SetLastError(STATUS_ACCESS_VIOLATION);
454 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
455 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
456 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
462 const CERT_SIGNED_CONTENT_INFO *info = pvStructInfo;
463 struct AsnEncodeSequenceItem items[] = {
464 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
465 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
466 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
469 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
470 items[2].encodeFunc = CRYPT_AsnEncodeBits;
471 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
472 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
477 SetLastError(STATUS_ACCESS_VIOLATION);
484 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
485 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
486 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
489 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
490 struct AsnEncodeSequenceItem items[] = {
491 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
492 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
495 TRACE("Encoding public key with OID %s\n",
496 debugstr_a(info->Algorithm.pszObjId));
497 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
498 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
503 /* Like in Windows, this blithely ignores the validity of the passed-in
504 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
505 * decode properly, see CRYPT_AsnDecodeCertInfo.
507 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
508 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
509 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
515 const CERT_INFO *info = pvStructInfo;
516 struct AsnEncodeSequenceItem items[10] = {
517 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
518 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
519 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
520 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
521 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
522 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
523 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfoNoNull, 0 },
526 struct AsnConstructedItem constructed = { 0 };
527 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
528 DWORD cItem = 7, cSwapped = 0;
530 if (info->IssuerUniqueId.cbData)
532 swapped[cSwapped].tag = ASN_CONTEXT | 1;
533 swapped[cSwapped].pvStructInfo = &info->IssuerUniqueId;
534 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
535 items[cItem].pvStructInfo = &swapped[cSwapped];
536 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
540 if (info->SubjectUniqueId.cbData)
542 swapped[cSwapped].tag = ASN_CONTEXT | 2;
543 swapped[cSwapped].pvStructInfo = &info->SubjectUniqueId;
544 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
545 items[cItem].pvStructInfo = &swapped[cSwapped];
546 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
550 if (info->cExtension)
553 constructed.pvStructInfo = &info->cExtension;
554 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
555 items[cItem].pvStructInfo = &constructed;
556 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
560 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
561 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
565 SetLastError(STATUS_ACCESS_VIOLATION);
572 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
573 BYTE *pbEncoded, DWORD *pcbEncoded)
575 struct AsnEncodeSequenceItem items[3] = {
576 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
577 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
583 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
585 if (entry->cExtension)
587 items[cItem].pvStructInfo = &entry->cExtension;
588 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
592 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
593 pbEncoded, pcbEncoded);
595 TRACE("returning %d (%08x)\n", ret, GetLastError());
599 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
600 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
601 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
603 DWORD bytesNeeded, dataLen, lenBytes, i;
604 const CRL_INFO *info = pvStructInfo;
605 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
608 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
618 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
619 bytesNeeded = 1 + lenBytes + dataLen;
621 *pcbEncoded = bytesNeeded;
624 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
625 pcbEncoded, bytesNeeded)))
629 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
630 pbEncoded = *(BYTE **)pbEncoded;
632 *out++ = ASN_SEQUENCEOF;
633 CRYPT_EncodeLen(dataLen, out, &lenBytes);
635 for (i = 0; i < info->cCRLEntry; i++)
637 DWORD size = dataLen;
639 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
643 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
644 CRYPT_FreeSpace(pEncodePara, pbEncoded);
651 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
652 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
653 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
655 const DWORD *ver = pvStructInfo;
658 /* CRL_V1 is not encoded */
665 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
666 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
670 /* Like in Windows, this blithely ignores the validity of the passed-in
671 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
672 * decode properly, see CRYPT_AsnDecodeCRLInfo.
674 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
675 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
676 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
682 const CRL_INFO *info = pvStructInfo;
683 struct AsnEncodeSequenceItem items[7] = {
684 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
685 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
686 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
687 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
690 struct AsnConstructedItem constructed[1] = { { 0 } };
691 DWORD cItem = 4, cConstructed = 0;
693 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
695 items[cItem].pvStructInfo = &info->NextUpdate;
696 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
701 items[cItem].pvStructInfo = info;
702 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
705 if (info->cExtension)
707 constructed[cConstructed].tag = 0;
708 constructed[cConstructed].pvStructInfo = &info->cExtension;
709 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
710 items[cItem].pvStructInfo = &constructed[cConstructed];
711 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
716 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
717 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
721 SetLastError(STATUS_ACCESS_VIOLATION);
728 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
732 struct AsnEncodeSequenceItem items[3] = {
733 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
739 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
743 items[cItem].pvStructInfo = &ext->fCritical;
744 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
747 items[cItem].pvStructInfo = &ext->Value;
748 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
751 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
752 pbEncoded, pcbEncoded);
753 TRACE("returning %d (%08x)\n", ret, GetLastError());
757 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
758 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
759 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
765 DWORD bytesNeeded, dataLen, lenBytes, i;
766 const CERT_EXTENSIONS *exts = pvStructInfo;
769 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
773 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
779 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
780 bytesNeeded = 1 + lenBytes + dataLen;
782 *pcbEncoded = bytesNeeded;
785 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
786 pbEncoded, pcbEncoded, bytesNeeded)))
790 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
791 pbEncoded = *(BYTE **)pbEncoded;
793 *out++ = ASN_SEQUENCEOF;
794 CRYPT_EncodeLen(dataLen, out, &lenBytes);
796 for (i = 0; i < exts->cExtension; i++)
798 DWORD size = dataLen;
800 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
805 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
806 CRYPT_FreeSpace(pEncodePara, pbEncoded);
813 SetLastError(STATUS_ACCESS_VIOLATION);
820 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
821 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
822 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
824 LPCSTR pszObjId = pvStructInfo;
825 DWORD bytesNeeded = 0, lenBytes;
830 TRACE("%s\n", debugstr_a(pszObjId));
837 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
839 SetLastError(CRYPT_E_ASN1_ERROR);
843 firstByte = val1 * 40 + val2;
844 ptr = pszObjId + firstPos;
854 /* note I assume each component is at most 32-bits long in base 2 */
855 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
857 if (val1 >= 0x10000000)
859 else if (val1 >= 0x200000)
861 else if (val1 >= 0x4000)
863 else if (val1 >= 0x80)
873 SetLastError(CRYPT_E_ASN1_ERROR);
877 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
881 bytesNeeded += 1 + lenBytes;
884 if (*pcbEncoded < bytesNeeded)
886 SetLastError(ERROR_MORE_DATA);
891 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
892 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
893 pbEncoded += lenBytes;
899 *pbEncoded++ = firstByte;
900 ptr = pszObjId + firstPos;
903 sscanf(ptr, "%d%n", &val, &pos);
905 unsigned char outBytes[5];
908 if (val >= 0x10000000)
910 else if (val >= 0x200000)
912 else if (val >= 0x4000)
914 else if (val >= 0x80)
918 for (i = numBytes; i > 0; i--)
920 outBytes[i - 1] = val & 0x7f;
923 for (i = 0; i < numBytes - 1; i++)
924 *pbEncoded++ = outBytes[i] | 0x80;
925 *pbEncoded++ = outBytes[i];
934 *pcbEncoded = bytesNeeded;
938 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
939 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
943 LPCSTR str = (LPCSTR)value->Value.pbData;
944 DWORD bytesNeeded, lenBytes, encodedLen;
946 encodedLen = value->Value.cbData ? value->Value.cbData : strlen(str);
947 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
948 bytesNeeded = 1 + lenBytes + encodedLen;
950 *pcbEncoded = bytesNeeded;
953 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
954 pbEncoded, pcbEncoded, bytesNeeded)))
956 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
957 pbEncoded = *(BYTE **)pbEncoded;
959 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
960 pbEncoded += lenBytes;
961 memcpy(pbEncoded, str, encodedLen);
967 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
968 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
972 LPCWSTR str = (LPCWSTR)value->Value.pbData;
973 DWORD bytesNeeded, lenBytes, strLen;
975 if (value->Value.cbData)
976 strLen = value->Value.cbData / sizeof(WCHAR);
977 else if (value->Value.pbData)
978 strLen = lstrlenW(str);
981 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
982 bytesNeeded = 1 + lenBytes + strLen * 2;
984 *pcbEncoded = bytesNeeded;
987 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
988 pbEncoded, pcbEncoded, bytesNeeded)))
992 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
993 pbEncoded = *(BYTE **)pbEncoded;
994 *pbEncoded++ = ASN_BMPSTRING;
995 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
996 pbEncoded += lenBytes;
997 for (i = 0; i < strLen; i++)
999 *pbEncoded++ = (str[i] & 0xff00) >> 8;
1000 *pbEncoded++ = str[i] & 0x00ff;
1007 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
1008 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1012 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1013 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
1015 if (value->Value.cbData)
1016 strLen = value->Value.cbData / sizeof(WCHAR);
1018 strLen = strlenW(str);
1021 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1023 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1024 bytesNeeded = 1 + lenBytes + encodedLen;
1026 *pcbEncoded = bytesNeeded;
1029 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1030 pbEncoded, pcbEncoded, bytesNeeded)))
1032 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1033 pbEncoded = *(BYTE **)pbEncoded;
1034 *pbEncoded++ = ASN_UTF8STRING;
1035 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1036 pbEncoded += lenBytes;
1037 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1038 bytesNeeded - lenBytes - 1, NULL, NULL);
1044 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1045 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1046 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1052 const CERT_NAME_VALUE *value = pvStructInfo;
1054 switch (value->dwValueType)
1056 case CERT_RDN_ANY_TYPE:
1057 /* explicitly disallowed */
1058 SetLastError(E_INVALIDARG);
1061 case CERT_RDN_ENCODED_BLOB:
1062 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1063 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1065 case CERT_RDN_OCTET_STRING:
1066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1067 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1069 case CERT_RDN_NUMERIC_STRING:
1070 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1071 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1073 case CERT_RDN_PRINTABLE_STRING:
1074 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1075 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1077 case CERT_RDN_TELETEX_STRING:
1078 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1079 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1081 case CERT_RDN_VIDEOTEX_STRING:
1082 ret = CRYPT_AsnEncodeStringCoerce(value,
1083 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1085 case CERT_RDN_IA5_STRING:
1086 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1087 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1089 case CERT_RDN_GRAPHIC_STRING:
1090 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1091 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1093 case CERT_RDN_VISIBLE_STRING:
1094 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1095 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1097 case CERT_RDN_GENERAL_STRING:
1098 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1099 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1101 case CERT_RDN_UNIVERSAL_STRING:
1102 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1103 SetLastError(CRYPT_E_ASN1_CHOICE);
1106 case CERT_RDN_BMP_STRING:
1107 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1108 pbEncoded, pcbEncoded);
1110 case CERT_RDN_UTF8_STRING:
1111 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1112 pbEncoded, pcbEncoded);
1115 SetLastError(CRYPT_E_ASN1_CHOICE);
1121 SetLastError(STATUS_ACCESS_VIOLATION);
1128 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1129 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1130 BYTE *pbEncoded, DWORD *pcbEncoded)
1132 DWORD bytesNeeded = 0, lenBytes, size;
1135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1136 0, NULL, NULL, &size);
1139 bytesNeeded += size;
1140 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1141 * with dwValueType, so "cast" it to get its encoded size
1143 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1144 0, NULL, NULL, &size);
1147 bytesNeeded += size;
1148 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1149 bytesNeeded += 1 + lenBytes;
1152 if (*pcbEncoded < bytesNeeded)
1154 SetLastError(ERROR_MORE_DATA);
1159 *pbEncoded++ = ASN_SEQUENCE;
1160 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1162 pbEncoded += lenBytes;
1163 size = bytesNeeded - 1 - lenBytes;
1164 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1165 attr->pszObjId, 0, NULL, pbEncoded, &size);
1169 size = bytesNeeded - 1 - lenBytes - size;
1170 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1171 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1178 *pcbEncoded = bytesNeeded;
1182 /* Have to propagate index of failing character */
1189 static int BLOBComp(const void *l, const void *r)
1191 const CRYPT_DER_BLOB *a = l, *b = r;
1194 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1195 ret = a->cbData - b->cbData;
1199 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1201 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1202 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1205 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1206 DWORD bytesNeeded = 0, lenBytes, i;
1209 for (i = 0; i < set->cBlob; i++)
1210 bytesNeeded += set->rgBlob[i].cbData;
1211 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1212 bytesNeeded += 1 + lenBytes;
1215 *pcbEncoded = bytesNeeded;
1218 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1219 pbEncoded, pcbEncoded, bytesNeeded)))
1221 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1222 pbEncoded = *(BYTE **)pbEncoded;
1223 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1224 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1225 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1226 pbEncoded += lenBytes;
1227 for (i = 0; i < set->cBlob; i++)
1229 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1230 pbEncoded += set->rgBlob[i].cbData;
1236 struct DERSetDescriptor
1242 CryptEncodeObjectExFunc encode;
1245 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1246 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1247 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1249 const struct DERSetDescriptor *desc = pvStructInfo;
1250 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1256 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1261 setOf.cBlob = desc->cItems;
1262 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1265 for (i = 0; ret && i < setOf.cBlob; i++)
1267 ret = desc->encode(dwCertEncodingType, lpszStructType,
1268 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1269 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1272 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1273 if (!setOf.rgBlob[i].pbData)
1276 ret = desc->encode(dwCertEncodingType, lpszStructType,
1277 (const BYTE *)desc->items + i * desc->itemSize +
1278 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1279 &setOf.rgBlob[i].cbData);
1281 /* Some functions propagate their errors through the size */
1283 *pcbEncoded = setOf.rgBlob[i].cbData;
1287 DWORD bytesNeeded = 0, lenBytes;
1289 for (i = 0; i < setOf.cBlob; i++)
1290 bytesNeeded += setOf.rgBlob[i].cbData;
1291 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1292 bytesNeeded += 1 + lenBytes;
1294 *pcbEncoded = bytesNeeded;
1295 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1296 pbEncoded, pcbEncoded, bytesNeeded)))
1298 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1299 pbEncoded = *(BYTE **)pbEncoded;
1300 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1302 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1303 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1304 pbEncoded += lenBytes;
1305 for (i = 0; i < setOf.cBlob; i++)
1307 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1308 setOf.rgBlob[i].cbData);
1309 pbEncoded += setOf.rgBlob[i].cbData;
1313 for (i = 0; i < setOf.cBlob; i++)
1314 CryptMemFree(setOf.rgBlob[i].pbData);
1315 CryptMemFree(setOf.rgBlob);
1319 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1320 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1324 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1333 setOf.cBlob = rdn->cRDNAttr;
1334 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1335 sizeof(CRYPT_DER_BLOB));
1339 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1341 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1343 setOf.rgBlob[i].cbData = 0;
1344 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1345 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1348 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1349 if (!setOf.rgBlob[i].pbData)
1352 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1353 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1354 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1358 /* Have to propagate index of failing character */
1359 *pcbEncoded = setOf.rgBlob[i].cbData;
1363 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1364 pbEncoded, pcbEncoded);
1365 for (i = 0; i < setOf.cBlob; i++)
1366 CryptMemFree(setOf.rgBlob[i].pbData);
1370 SetLastError(STATUS_ACCESS_VIOLATION);
1374 CryptMemFree(setOf.rgBlob);
1378 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1379 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1380 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1382 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1383 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1384 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1387 const CERT_NAME_VALUE *value = pvStructInfo;
1390 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1391 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1392 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1394 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1395 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1399 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1400 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1401 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1407 const CERT_NAME_INFO *info = pvStructInfo;
1408 DWORD bytesNeeded = 0, lenBytes, size, i;
1410 TRACE("encoding name with %d RDNs\n", info->cRDN);
1412 for (i = 0; ret && i < info->cRDN; i++)
1414 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1415 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1417 bytesNeeded += size;
1421 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1422 bytesNeeded += 1 + lenBytes;
1426 *pcbEncoded = bytesNeeded;
1429 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1430 pbEncoded, pcbEncoded, bytesNeeded)))
1434 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1435 pbEncoded = *(BYTE **)pbEncoded;
1437 *out++ = ASN_SEQUENCEOF;
1438 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1440 for (i = 0; ret && i < info->cRDN; i++)
1443 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1444 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1449 bytesNeeded -= size;
1454 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1455 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1462 SetLastError(STATUS_ACCESS_VIOLATION);
1469 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1470 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1471 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1473 const DWORD *ver = pvStructInfo;
1476 /* CTL_V1 is not encoded */
1483 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1484 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1488 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1489 * if they are empty and the OID is not empty (otherwise omits them.)
1491 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1492 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1493 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1496 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1498 struct AsnEncodeSequenceItem items[2] = {
1499 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1505 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1506 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1509 if (algo->Parameters.cbData)
1510 items[cItem].pvStructInfo = &algo->Parameters;
1512 items[cItem].pvStructInfo = &nullBlob;
1513 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1516 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1517 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1521 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1522 BYTE *pbEncoded, DWORD *pcbEncoded)
1524 struct AsnEncodeSequenceItem items[2] = {
1525 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1526 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1530 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1531 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1541 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1542 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1543 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1546 DWORD bytesNeeded, dataLen, lenBytes, i;
1547 const struct CTLEntries *entries = pvStructInfo;
1550 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1554 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1560 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1561 bytesNeeded = 1 + lenBytes + dataLen;
1563 *pcbEncoded = bytesNeeded;
1566 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1567 pbEncoded, pcbEncoded, bytesNeeded)))
1571 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1572 pbEncoded = *(BYTE **)pbEncoded;
1574 *out++ = ASN_SEQUENCEOF;
1575 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1577 for (i = 0; ret && i < entries->cEntry; i++)
1579 DWORD size = dataLen;
1581 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1586 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1587 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1594 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1595 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1596 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1602 const CTL_INFO *info = pvStructInfo;
1603 struct AsnEncodeSequenceItem items[9] = {
1604 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1605 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1607 struct AsnConstructedItem constructed = { 0 };
1610 if (info->ListIdentifier.cbData)
1612 items[cItem].pvStructInfo = &info->ListIdentifier;
1613 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1616 if (info->SequenceNumber.cbData)
1618 items[cItem].pvStructInfo = &info->SequenceNumber;
1619 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1622 items[cItem].pvStructInfo = &info->ThisUpdate;
1623 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1625 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1627 items[cItem].pvStructInfo = &info->NextUpdate;
1628 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1631 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1632 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1634 if (info->cCTLEntry)
1636 items[cItem].pvStructInfo = &info->cCTLEntry;
1637 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1640 if (info->cExtension)
1642 constructed.tag = 0;
1643 constructed.pvStructInfo = &info->cExtension;
1644 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1645 items[cItem].pvStructInfo = &constructed;
1646 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1649 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1650 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1654 SetLastError(STATUS_ACCESS_VIOLATION);
1660 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1661 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1662 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1668 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1670 if (!capability->pszObjId)
1671 SetLastError(E_INVALIDARG);
1674 struct AsnEncodeSequenceItem items[] = {
1675 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1676 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1679 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1680 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1686 SetLastError(STATUS_ACCESS_VIOLATION);
1692 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1693 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1694 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1700 DWORD bytesNeeded, dataLen, lenBytes, i;
1701 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1704 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1708 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1709 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1715 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1716 bytesNeeded = 1 + lenBytes + dataLen;
1718 *pcbEncoded = bytesNeeded;
1721 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1722 pbEncoded, pcbEncoded, bytesNeeded)))
1726 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1727 pbEncoded = *(BYTE **)pbEncoded;
1729 *out++ = ASN_SEQUENCEOF;
1730 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1732 for (i = 0; i < capabilities->cCapability; i++)
1734 DWORD size = dataLen;
1736 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1737 NULL, &capabilities->rgCapability[i], 0, NULL,
1742 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1743 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1750 SetLastError(STATUS_ACCESS_VIOLATION);
1756 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1757 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1758 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1760 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1761 DWORD bytesNeeded, dataLen, lenBytes, i;
1764 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1768 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1769 ¬iceRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1775 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1776 bytesNeeded = 1 + lenBytes + dataLen;
1778 *pcbEncoded = bytesNeeded;
1781 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1782 pcbEncoded, bytesNeeded)))
1786 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1787 pbEncoded = *(BYTE **)pbEncoded;
1789 *out++ = ASN_SEQUENCE;
1790 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1792 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1794 DWORD size = dataLen;
1796 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1797 ¬iceRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1801 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1802 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1809 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1810 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1811 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1813 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1815 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1816 { 0, (LPBYTE)noticeRef->pszOrganization } };
1817 struct AsnEncodeSequenceItem items[] = {
1818 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1819 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1822 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1823 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1828 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1829 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1830 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1837 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1838 struct AsnEncodeSequenceItem items[2];
1839 CERT_NAME_VALUE displayTextValue;
1843 if (notice->pNoticeReference)
1845 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1846 items[cItem].pvStructInfo = notice->pNoticeReference;
1849 if (notice->pszDisplayText)
1851 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1852 displayTextValue.Value.cbData = 0;
1853 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1854 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1855 items[cItem].pvStructInfo = &displayTextValue;
1858 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1859 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1863 SetLastError(STATUS_ACCESS_VIOLATION);
1869 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1870 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1871 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1877 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1879 if (!attr->pszObjId)
1880 SetLastError(E_INVALIDARG);
1883 struct AsnEncodeSequenceItem items[2] = {
1884 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1885 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1888 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1889 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1895 SetLastError(STATUS_ACCESS_VIOLATION);
1901 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1902 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1903 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1909 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1910 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1911 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1913 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1914 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1918 SetLastError(STATUS_ACCESS_VIOLATION);
1924 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1925 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1926 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1927 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1930 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1931 struct AsnEncodeSequenceItem items[2] = {
1932 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1935 struct AsnConstructedItem constructed = { 0 };
1938 if (info->Content.cbData)
1940 constructed.tag = 0;
1941 constructed.pvStructInfo = &info->Content;
1942 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1943 items[cItem].pvStructInfo = &constructed;
1944 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1947 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1948 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1951 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1952 void *pvData, DWORD *pcbData)
1954 struct AsnEncodeSequenceItem items[] = {
1955 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1956 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1958 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1959 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1962 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1963 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1966 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1967 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1968 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1974 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1976 if (!info->pszObjId)
1977 SetLastError(E_INVALIDARG);
1979 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1980 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1985 SetLastError(STATUS_ACCESS_VIOLATION);
1991 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1992 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1996 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1997 DWORD bytesNeeded, lenBytes, encodedLen;
1999 if (value->Value.cbData)
2000 encodedLen = value->Value.cbData / sizeof(WCHAR);
2002 encodedLen = strlenW(str);
2005 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2006 bytesNeeded = 1 + lenBytes + encodedLen;
2008 *pcbEncoded = bytesNeeded;
2011 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2012 pbEncoded, pcbEncoded, bytesNeeded)))
2016 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2017 pbEncoded = *(BYTE **)pbEncoded;
2019 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2020 pbEncoded += lenBytes;
2021 for (i = 0; i < encodedLen; i++)
2022 *pbEncoded++ = (BYTE)str[i];
2028 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
2029 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2033 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2034 DWORD bytesNeeded, lenBytes, encodedLen;
2036 if (value->Value.cbData)
2037 encodedLen = value->Value.cbData / sizeof(WCHAR);
2039 encodedLen = strlenW(str);
2042 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2043 bytesNeeded = 1 + lenBytes + encodedLen;
2045 *pcbEncoded = bytesNeeded;
2048 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2049 pbEncoded, pcbEncoded, bytesNeeded)))
2054 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2055 ptr = *(BYTE **)pbEncoded;
2058 *ptr++ = ASN_NUMERICSTRING;
2059 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2061 for (i = 0; ret && i < encodedLen; i++)
2063 if (isdigitW(str[i]))
2064 *ptr++ = (BYTE)str[i];
2068 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2072 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2073 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2079 static inline int isprintableW(WCHAR wc)
2081 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2082 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2083 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2086 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2087 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2091 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2092 DWORD bytesNeeded, lenBytes, encodedLen;
2094 if (value->Value.cbData)
2095 encodedLen = value->Value.cbData / sizeof(WCHAR);
2097 encodedLen = strlenW(str);
2100 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2101 bytesNeeded = 1 + lenBytes + encodedLen;
2103 *pcbEncoded = bytesNeeded;
2106 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2107 pbEncoded, pcbEncoded, bytesNeeded)))
2112 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2113 ptr = *(BYTE **)pbEncoded;
2116 *ptr++ = ASN_PRINTABLESTRING;
2117 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2119 for (i = 0; ret && i < encodedLen; i++)
2121 if (isprintableW(str[i]))
2122 *ptr++ = (BYTE)str[i];
2126 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2130 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2131 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2137 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2138 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2142 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2143 DWORD bytesNeeded, lenBytes, encodedLen;
2145 if (value->Value.cbData)
2146 encodedLen = value->Value.cbData / sizeof(WCHAR);
2148 encodedLen = strlenW(str);
2151 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2152 bytesNeeded = 1 + lenBytes + encodedLen;
2154 *pcbEncoded = bytesNeeded;
2157 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2158 pbEncoded, pcbEncoded, bytesNeeded)))
2163 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2164 ptr = *(BYTE **)pbEncoded;
2167 *ptr++ = ASN_IA5STRING;
2168 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2170 for (i = 0; ret && i < encodedLen; i++)
2173 *ptr++ = (BYTE)str[i];
2177 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2181 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2182 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2188 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2189 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2193 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2194 DWORD bytesNeeded, lenBytes, strLen;
2196 /* FIXME: doesn't handle composite characters */
2197 if (value->Value.cbData)
2198 strLen = value->Value.cbData / sizeof(WCHAR);
2200 strLen = strlenW(str);
2203 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2204 bytesNeeded = 1 + lenBytes + strLen * 4;
2206 *pcbEncoded = bytesNeeded;
2209 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2210 pbEncoded, pcbEncoded, bytesNeeded)))
2214 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2215 pbEncoded = *(BYTE **)pbEncoded;
2216 *pbEncoded++ = ASN_UNIVERSALSTRING;
2217 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2218 pbEncoded += lenBytes;
2219 for (i = 0; i < strLen; i++)
2223 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2224 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2231 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2232 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2233 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2239 const CERT_NAME_VALUE *value = pvStructInfo;
2241 switch (value->dwValueType)
2243 case CERT_RDN_ANY_TYPE:
2244 case CERT_RDN_ENCODED_BLOB:
2245 case CERT_RDN_OCTET_STRING:
2246 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2248 case CERT_RDN_NUMERIC_STRING:
2249 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2250 pbEncoded, pcbEncoded);
2252 case CERT_RDN_PRINTABLE_STRING:
2253 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2254 pbEncoded, pcbEncoded);
2256 case CERT_RDN_TELETEX_STRING:
2257 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2258 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2260 case CERT_RDN_VIDEOTEX_STRING:
2261 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2262 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2264 case CERT_RDN_IA5_STRING:
2265 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2266 pbEncoded, pcbEncoded);
2268 case CERT_RDN_GRAPHIC_STRING:
2269 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2270 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2272 case CERT_RDN_VISIBLE_STRING:
2273 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2274 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2276 case CERT_RDN_GENERAL_STRING:
2277 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2278 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2280 case CERT_RDN_UNIVERSAL_STRING:
2281 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2282 pbEncoded, pcbEncoded);
2284 case CERT_RDN_BMP_STRING:
2285 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2286 pbEncoded, pcbEncoded);
2288 case CERT_RDN_UTF8_STRING:
2289 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2290 pbEncoded, pcbEncoded);
2293 SetLastError(CRYPT_E_ASN1_CHOICE);
2298 SetLastError(STATUS_ACCESS_VIOLATION);
2304 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2305 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2306 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2312 const CERT_NAME_INFO *info = pvStructInfo;
2313 DWORD bytesNeeded = 0, lenBytes, size, i;
2315 TRACE("encoding name with %d RDNs\n", info->cRDN);
2317 for (i = 0; ret && i < info->cRDN; i++)
2319 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2320 CRYPT_AsnEncodeNameValue, NULL, &size);
2322 bytesNeeded += size;
2324 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2325 bytesNeeded += 1 + lenBytes;
2329 *pcbEncoded = bytesNeeded;
2332 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2333 pbEncoded, pcbEncoded, bytesNeeded)))
2337 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2338 pbEncoded = *(BYTE **)pbEncoded;
2340 *out++ = ASN_SEQUENCEOF;
2341 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2343 for (i = 0; ret && i < info->cRDN; i++)
2346 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2347 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2351 bytesNeeded -= size;
2354 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2355 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2362 SetLastError(STATUS_ACCESS_VIOLATION);
2369 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2370 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2371 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2373 BOOL val = *(const BOOL *)pvStructInfo, ret;
2382 else if (*pcbEncoded < 3)
2385 SetLastError(ERROR_MORE_DATA);
2391 *pbEncoded++ = ASN_BOOL;
2393 *pbEncoded++ = val ? 0xff : 0;
2396 TRACE("returning %d (%08x)\n", ret, GetLastError());
2400 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2401 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2402 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2404 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2410 switch (entry->dwAltNameChoice)
2412 case CERT_ALT_NAME_RFC822_NAME:
2413 case CERT_ALT_NAME_DNS_NAME:
2414 case CERT_ALT_NAME_URL:
2415 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2416 if (entry->u.pwszURL)
2420 /* Not + 1: don't encode the NULL-terminator */
2421 dataLen = lstrlenW(entry->u.pwszURL);
2422 for (i = 0; ret && i < dataLen; i++)
2424 if (entry->u.pwszURL[i] > 0x7f)
2426 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2435 case CERT_ALT_NAME_DIRECTORY_NAME:
2436 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2437 dataLen = entry->u.DirectoryName.cbData;
2439 case CERT_ALT_NAME_IP_ADDRESS:
2440 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2441 dataLen = entry->u.IPAddress.cbData;
2443 case CERT_ALT_NAME_REGISTERED_ID:
2445 struct AsnEncodeTagSwappedItem swapped =
2446 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2447 CRYPT_AsnEncodeOid };
2449 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2452 case CERT_ALT_NAME_OTHER_NAME:
2453 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2456 SetLastError(E_INVALIDARG);
2461 DWORD bytesNeeded, lenBytes;
2463 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2464 bytesNeeded = 1 + dataLen + lenBytes;
2466 *pcbEncoded = bytesNeeded;
2467 else if (*pcbEncoded < bytesNeeded)
2469 SetLastError(ERROR_MORE_DATA);
2470 *pcbEncoded = bytesNeeded;
2476 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2477 pbEncoded += lenBytes;
2478 switch (entry->dwAltNameChoice)
2480 case CERT_ALT_NAME_RFC822_NAME:
2481 case CERT_ALT_NAME_DNS_NAME:
2482 case CERT_ALT_NAME_URL:
2486 for (i = 0; i < dataLen; i++)
2487 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2490 case CERT_ALT_NAME_DIRECTORY_NAME:
2491 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2493 case CERT_ALT_NAME_IP_ADDRESS:
2494 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2498 *pcbEncoded = bytesNeeded;
2501 TRACE("returning %d (%08x)\n", ret, GetLastError());
2505 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2506 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2507 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2513 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2514 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2515 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2516 struct AsnConstructedItem constructed = { 0 };
2517 DWORD cItem = 0, cSwapped = 0;
2519 if (info->KeyId.cbData)
2521 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2522 swapped[cSwapped].pvStructInfo = &info->KeyId;
2523 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2524 items[cItem].pvStructInfo = &swapped[cSwapped];
2525 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2529 if (info->CertIssuer.cbData)
2531 constructed.tag = 1;
2532 constructed.pvStructInfo = &info->CertIssuer;
2533 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2534 items[cItem].pvStructInfo = &constructed;
2535 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2538 if (info->CertSerialNumber.cbData)
2540 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2541 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2542 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2543 items[cItem].pvStructInfo = &swapped[cSwapped];
2544 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2548 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2549 pEncodePara, pbEncoded, pcbEncoded);
2553 SetLastError(STATUS_ACCESS_VIOLATION);
2560 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2561 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2562 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2568 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2569 DWORD bytesNeeded, dataLen, lenBytes, i;
2572 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2573 * can't encode an erroneous entry index if it's bigger than this.
2575 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2579 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2580 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2583 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2585 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2586 * the bad character, now set the index of the bad
2589 *pcbEncoded = (BYTE)i <<
2590 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2595 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2596 bytesNeeded = 1 + lenBytes + dataLen;
2599 *pcbEncoded = bytesNeeded;
2604 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2605 pbEncoded, pcbEncoded, bytesNeeded)))
2609 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2610 pbEncoded = *(BYTE **)pbEncoded;
2612 *out++ = ASN_SEQUENCEOF;
2613 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2615 for (i = 0; ret && i < info->cAltEntry; i++)
2617 DWORD len = dataLen;
2619 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2620 NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2627 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2628 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2635 SetLastError(STATUS_ACCESS_VIOLATION);
2642 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2643 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2644 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2650 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2651 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2652 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2653 DWORD cItem = 0, cSwapped = 0;
2655 if (info->KeyId.cbData)
2657 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2658 swapped[cSwapped].pvStructInfo = &info->KeyId;
2659 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2660 items[cItem].pvStructInfo = &swapped[cSwapped];
2661 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2665 if (info->AuthorityCertIssuer.cAltEntry)
2667 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2668 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2669 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2670 items[cItem].pvStructInfo = &swapped[cSwapped];
2671 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2675 if (info->AuthorityCertSerialNumber.cbData)
2677 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2678 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2679 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2680 items[cItem].pvStructInfo = &swapped[cSwapped];
2681 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2685 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2686 pEncodePara, pbEncoded, pcbEncoded);
2690 SetLastError(STATUS_ACCESS_VIOLATION);
2697 static BOOL CRYPT_AsnEncodeAccessDescription(
2698 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2700 struct AsnEncodeSequenceItem items[] = {
2701 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2702 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2705 if (!descr->pszAccessMethod)
2707 SetLastError(E_INVALIDARG);
2710 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2711 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2714 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2715 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2716 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2722 DWORD bytesNeeded, dataLen, lenBytes, i;
2723 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2726 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2730 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2737 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2738 bytesNeeded = 1 + lenBytes + dataLen;
2740 *pcbEncoded = bytesNeeded;
2743 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2744 pbEncoded, pcbEncoded, bytesNeeded)))
2748 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2749 pbEncoded = *(BYTE **)pbEncoded;
2751 *out++ = ASN_SEQUENCEOF;
2752 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2754 for (i = 0; i < info->cAccDescr; i++)
2756 DWORD size = dataLen;
2758 ret = CRYPT_AsnEncodeAccessDescription(
2759 &info->rgAccDescr[i], out, &size);
2763 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2764 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2771 SetLastError(STATUS_ACCESS_VIOLATION);
2778 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2779 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2780 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2786 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2787 struct AsnEncodeSequenceItem items[3] = {
2788 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2793 if (info->fPathLenConstraint)
2795 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2796 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2799 if (info->cSubtreesConstraint)
2801 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2802 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2805 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2806 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2810 SetLastError(STATUS_ACCESS_VIOLATION);
2817 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2818 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2819 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2825 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2826 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2831 items[cItem].pvStructInfo = &info->fCA;
2832 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2835 if (info->fPathLenConstraint)
2837 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2838 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2841 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2842 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2846 SetLastError(STATUS_ACCESS_VIOLATION);
2853 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2854 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2855 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2857 const CERT_POLICY_INFO *info = pvStructInfo;
2860 if (!info->cPolicyQualifier)
2867 struct AsnEncodeSequenceItem items[2] = {
2868 { NULL, CRYPT_AsnEncodeOid, 0 },
2869 { NULL, CRYPT_CopyEncodedBlob, 0 },
2871 DWORD bytesNeeded = 0, lenBytes, size, i;
2874 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2876 items[0].pvStructInfo =
2877 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2878 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2879 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2880 sizeof(items) / sizeof(items[0]),
2881 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2883 bytesNeeded += size;
2885 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2886 bytesNeeded += 1 + lenBytes;
2890 *pcbEncoded = bytesNeeded;
2893 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2894 pbEncoded, pcbEncoded, bytesNeeded)))
2898 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2899 pbEncoded = *(BYTE **)pbEncoded;
2901 *out++ = ASN_SEQUENCEOF;
2902 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2904 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2906 items[0].pvStructInfo =
2907 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2908 items[1].pvStructInfo =
2909 &info->rgPolicyQualifier[i].Qualifier;
2911 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2912 sizeof(items) / sizeof(items[0]),
2913 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
2917 bytesNeeded -= size;
2920 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2921 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2929 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2930 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2933 struct AsnEncodeSequenceItem items[2] = {
2934 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2935 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2939 if (!info->pszPolicyIdentifier)
2941 SetLastError(E_INVALIDARG);
2944 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2945 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2949 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2950 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2951 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2957 const CERT_POLICIES_INFO *info = pvStructInfo;
2958 DWORD bytesNeeded = 0, lenBytes, size, i;
2961 for (i = 0; ret && i < info->cPolicyInfo; i++)
2963 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2964 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2967 bytesNeeded += size;
2969 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2970 bytesNeeded += 1 + lenBytes;
2974 *pcbEncoded = bytesNeeded;
2977 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2978 pbEncoded, pcbEncoded, bytesNeeded)))
2982 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2983 pbEncoded = *(BYTE **)pbEncoded;
2985 *out++ = ASN_SEQUENCEOF;
2986 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2988 for (i = 0; ret && i < info->cPolicyInfo; i++)
2991 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2992 &info->rgPolicyInfo[i],
2993 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
2997 bytesNeeded -= size;
3000 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3001 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3008 SetLastError(STATUS_ACCESS_VIOLATION);
3014 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
3015 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
3018 struct AsnEncodeSequenceItem items[] = {
3019 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3020 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
3023 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3025 SetLastError(E_INVALIDARG);
3028 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3029 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
3032 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
3033 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3034 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3040 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3041 DWORD bytesNeeded = 0, lenBytes, size, i;
3044 for (i = 0; ret && i < info->cPolicyMapping; i++)
3046 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3047 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3050 bytesNeeded += size;
3052 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3053 bytesNeeded += 1 + lenBytes;
3057 *pcbEncoded = bytesNeeded;
3060 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3061 pbEncoded, pcbEncoded, bytesNeeded)))
3065 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3066 pbEncoded = *(BYTE **)pbEncoded;
3068 *out++ = ASN_SEQUENCEOF;
3069 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3071 for (i = 0; ret && i < info->cPolicyMapping; i++)
3074 ret = CRYPT_AsnEncodeCertPolicyMapping(
3075 dwCertEncodingType, &info->rgPolicyMapping[i],
3076 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
3080 bytesNeeded -= size;
3083 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3084 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3091 SetLastError(STATUS_ACCESS_VIOLATION);
3097 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3098 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3099 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3106 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3107 struct AsnEncodeSequenceItem items[2];
3108 struct AsnEncodeTagSwappedItem swapped[2];
3109 DWORD cItem = 0, cSwapped = 0;
3111 if (info->fRequireExplicitPolicy)
3113 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3114 swapped[cSwapped].pvStructInfo =
3115 &info->dwRequireExplicitPolicySkipCerts;
3116 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3117 items[cItem].pvStructInfo = &swapped[cSwapped];
3118 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3122 if (info->fInhibitPolicyMapping)
3124 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3125 swapped[cSwapped].pvStructInfo =
3126 &info->dwInhibitPolicyMappingSkipCerts;
3127 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3128 items[cItem].pvStructInfo = &swapped[cSwapped];
3129 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3133 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3134 dwFlags, NULL, pbEncoded, pcbEncoded);
3138 SetLastError(STATUS_ACCESS_VIOLATION);
3144 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3145 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3146 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3152 const BLOBHEADER *hdr = pvStructInfo;
3154 if (hdr->bType != PUBLICKEYBLOB)
3156 SetLastError(E_INVALIDARG);
3161 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3162 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3163 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3164 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3165 struct AsnEncodeSequenceItem items[] = {
3166 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3167 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3170 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3171 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3177 SetLastError(STATUS_ACCESS_VIOLATION);
3184 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3185 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3186 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3192 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3193 DWORD bytesNeeded, lenBytes;
3195 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3196 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3198 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3199 bytesNeeded = 1 + lenBytes + blob->cbData;
3202 *pcbEncoded = bytesNeeded;
3207 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3208 pcbEncoded, bytesNeeded)))
3210 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3211 pbEncoded = *(BYTE **)pbEncoded;
3212 *pbEncoded++ = ASN_OCTETSTRING;
3213 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3214 pbEncoded += lenBytes;
3216 memcpy(pbEncoded, blob->pbData, blob->cbData);
3222 SetLastError(STATUS_ACCESS_VIOLATION);
3226 TRACE("returning %d (%08x)\n", ret, GetLastError());
3230 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3231 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3232 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3238 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3239 DWORD bytesNeeded, lenBytes, dataBytes;
3242 /* yep, MS allows cUnusedBits to be >= 8 */
3243 if (!blob->cUnusedBits)
3245 dataBytes = blob->cbData;
3248 else if (blob->cbData * 8 > blob->cUnusedBits)
3250 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3251 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3259 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3260 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3263 *pcbEncoded = bytesNeeded;
3268 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3269 pcbEncoded, bytesNeeded)))
3271 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3272 pbEncoded = *(BYTE **)pbEncoded;
3273 *pbEncoded++ = ASN_BITSTRING;
3274 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3275 pbEncoded += lenBytes;
3276 *pbEncoded++ = unusedBits;
3279 BYTE mask = 0xff << unusedBits;
3283 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3284 pbEncoded += dataBytes - 1;
3286 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3293 SetLastError(STATUS_ACCESS_VIOLATION);
3300 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3301 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3302 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3308 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3309 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3314 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3319 for (i = 0; i < newBlob.cbData; i++)
3320 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3326 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3327 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3328 CryptMemFree(newBlob.pbData);
3332 SetLastError(STATUS_ACCESS_VIOLATION);
3339 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3340 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3341 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3343 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3345 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3346 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3349 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3350 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3351 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3357 DWORD significantBytes, lenBytes, bytesNeeded;
3360 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3362 significantBytes = blob->cbData;
3363 if (significantBytes)
3365 if (blob->pbData[significantBytes - 1] & 0x80)
3367 /* negative, lop off leading (little-endian) 0xffs */
3368 for (; significantBytes > 0 &&
3369 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3371 if (blob->pbData[significantBytes - 1] < 0x80)
3379 /* positive, lop off leading (little-endian) zeroes */
3380 for (; significantBytes > 0 &&
3381 !blob->pbData[significantBytes - 1]; significantBytes--)
3383 if (significantBytes == 0)
3384 significantBytes = 1;
3385 if (blob->pbData[significantBytes - 1] > 0x7f)
3393 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3395 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3396 bytesNeeded = 1 + lenBytes + significantBytes;
3401 *pcbEncoded = bytesNeeded;
3406 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3407 pcbEncoded, bytesNeeded)))
3409 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3410 pbEncoded = *(BYTE **)pbEncoded;
3411 *pbEncoded++ = ASN_INTEGER;
3414 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3415 pbEncoded += lenBytes;
3416 *pbEncoded++ = padByte;
3420 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3421 pbEncoded += lenBytes;
3423 for (; significantBytes > 0; significantBytes--)
3424 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3430 SetLastError(STATUS_ACCESS_VIOLATION);
3437 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3438 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3439 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3445 DWORD significantBytes, lenBytes, bytesNeeded;
3447 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3449 significantBytes = blob->cbData;
3450 if (significantBytes)
3452 /* positive, lop off leading (little-endian) zeroes */
3453 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3456 if (significantBytes == 0)
3457 significantBytes = 1;
3458 if (blob->pbData[significantBytes - 1] > 0x7f)
3462 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3464 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3465 bytesNeeded = 1 + lenBytes + significantBytes;
3470 *pcbEncoded = bytesNeeded;
3475 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3476 pcbEncoded, bytesNeeded)))
3478 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3479 pbEncoded = *(BYTE **)pbEncoded;
3480 *pbEncoded++ = ASN_INTEGER;
3483 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3484 pbEncoded += lenBytes;
3489 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3490 pbEncoded += lenBytes;
3492 for (; significantBytes > 0; significantBytes--)
3493 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3499 SetLastError(STATUS_ACCESS_VIOLATION);
3506 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3510 CRYPT_INTEGER_BLOB blob;
3513 /* Encode as an unsigned integer, then change the tag to enumerated */
3514 blob.cbData = sizeof(DWORD);
3515 blob.pbData = (BYTE *)pvStructInfo;
3516 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3517 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3518 if (ret && pbEncoded)
3520 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3521 pbEncoded = *(BYTE **)pbEncoded;
3522 pbEncoded[0] = ASN_ENUMERATED;
3527 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3528 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3529 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3536 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3537 * temporary buffer because the output buffer is not NULL-terminated.
3540 static const DWORD bytesNeeded = sizeof(buf) - 1;
3544 *pcbEncoded = bytesNeeded;
3549 /* Sanity check the year, this is a two-digit year format */
3550 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3551 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3553 SetLastError(CRYPT_E_BAD_ENCODE);
3558 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3559 pbEncoded, pcbEncoded, bytesNeeded)))
3561 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3562 pbEncoded = *(BYTE **)pbEncoded;
3563 buf[0] = ASN_UTCTIME;
3564 buf[1] = bytesNeeded - 2;
3565 snprintf(buf + 2, sizeof(buf) - 2,
3566 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3567 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3568 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3569 sysTime.wMinute, sysTime.wSecond);
3570 memcpy(pbEncoded, buf, bytesNeeded);
3577 SetLastError(STATUS_ACCESS_VIOLATION);
3584 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3585 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3586 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3593 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3594 * temporary buffer because the output buffer is not NULL-terminated.
3597 static const DWORD bytesNeeded = sizeof(buf) - 1;
3601 *pcbEncoded = bytesNeeded;
3606 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3608 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3609 pcbEncoded, bytesNeeded);
3612 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3613 pbEncoded = *(BYTE **)pbEncoded;
3614 buf[0] = ASN_GENERALTIME;
3615 buf[1] = bytesNeeded - 2;
3616 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3617 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3618 sysTime.wMinute, sysTime.wSecond);
3619 memcpy(pbEncoded, buf, bytesNeeded);
3625 SetLastError(STATUS_ACCESS_VIOLATION);
3632 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3633 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3634 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3642 /* Check the year, if it's in the UTCTime range call that encode func */
3643 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3645 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3646 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3647 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3649 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3650 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3655 SetLastError(STATUS_ACCESS_VIOLATION);
3662 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3663 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3664 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3670 DWORD bytesNeeded, dataLen, lenBytes, i;
3671 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3673 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3674 dataLen += seq->rgValue[i].cbData;
3675 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3676 bytesNeeded = 1 + lenBytes + dataLen;
3679 *pcbEncoded = bytesNeeded;
3684 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3685 pcbEncoded, bytesNeeded)))
3687 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3688 pbEncoded = *(BYTE **)pbEncoded;
3689 *pbEncoded++ = ASN_SEQUENCEOF;
3690 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3691 pbEncoded += lenBytes;
3692 for (i = 0; i < seq->cValue; i++)
3694 memcpy(pbEncoded, seq->rgValue[i].pbData,
3695 seq->rgValue[i].cbData);
3696 pbEncoded += seq->rgValue[i].cbData;
3703 SetLastError(STATUS_ACCESS_VIOLATION);
3710 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3711 BYTE *pbEncoded, DWORD *pcbEncoded)
3714 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3715 struct AsnConstructedItem constructed = { 0 };
3716 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3717 DWORD cItem = 0, cSwapped = 0;
3719 switch (distPoint->DistPointName.dwDistPointNameChoice)
3721 case CRL_DIST_POINT_NO_NAME:
3724 case CRL_DIST_POINT_FULL_NAME:
3725 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3726 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3727 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3728 constructed.tag = 0;
3729 constructed.pvStructInfo = &swapped[cSwapped];
3730 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3731 items[cItem].pvStructInfo = &constructed;
3732 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3736 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3737 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3743 if (ret && distPoint->ReasonFlags.cbData)
3745 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3746 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3747 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3748 items[cItem].pvStructInfo = &swapped[cSwapped];
3749 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3753 if (ret && distPoint->CRLIssuer.cAltEntry)
3755 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3756 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3757 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3758 items[cItem].pvStructInfo = &swapped[cSwapped];
3759 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3764 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3765 pbEncoded, pcbEncoded);
3769 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3770 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3771 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3777 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3779 if (!info->cDistPoint)
3781 SetLastError(E_INVALIDARG);
3786 DWORD bytesNeeded, dataLen, lenBytes, i;
3789 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3793 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3797 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3799 /* Have to propagate index of failing character */
3805 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3806 bytesNeeded = 1 + lenBytes + dataLen;
3809 *pcbEncoded = bytesNeeded;
3814 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3815 pbEncoded, pcbEncoded, bytesNeeded)))
3819 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3820 pbEncoded = *(BYTE **)pbEncoded;
3822 *out++ = ASN_SEQUENCEOF;
3823 CRYPT_EncodeLen(dataLen, out, &lenBytes);
3825 for (i = 0; ret && i < info->cDistPoint; i++)
3827 DWORD len = dataLen;
3829 ret = CRYPT_AsnEncodeDistPoint(
3830 &info->rgDistPoint[i], out, &len);
3837 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3838 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3846 SetLastError(STATUS_ACCESS_VIOLATION);
3853 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3854 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3855 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3861 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3862 DWORD bytesNeeded = 0, lenBytes, size, i;
3865 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3867 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3868 usage->rgpszUsageIdentifier[i],
3869 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3871 bytesNeeded += size;
3873 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3874 bytesNeeded += 1 + lenBytes;
3878 *pcbEncoded = bytesNeeded;
3881 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3882 pbEncoded, pcbEncoded, bytesNeeded)))
3886 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3887 pbEncoded = *(BYTE **)pbEncoded;
3889 *out++ = ASN_SEQUENCEOF;
3890 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3892 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3895 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3896 usage->rgpszUsageIdentifier[i],
3897 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
3901 bytesNeeded -= size;
3904 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3905 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3912 SetLastError(STATUS_ACCESS_VIOLATION);
3919 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3920 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3921 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3927 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3928 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3929 struct AsnConstructedItem constructed = { 0 };
3930 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3931 DWORD cItem = 0, cSwapped = 0;
3934 switch (point->DistPointName.dwDistPointNameChoice)
3936 case CRL_DIST_POINT_NO_NAME:
3939 case CRL_DIST_POINT_FULL_NAME:
3940 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3941 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3942 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3943 constructed.tag = 0;
3944 constructed.pvStructInfo = &swapped[cSwapped];
3945 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3946 items[cItem].pvStructInfo = &constructed;
3947 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3952 SetLastError(E_INVALIDARG);
3955 if (ret && point->fOnlyContainsUserCerts)
3957 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3958 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3959 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3960 items[cItem].pvStructInfo = &swapped[cSwapped];
3961 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3965 if (ret && point->fOnlyContainsCACerts)
3967 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3968 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3969 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3970 items[cItem].pvStructInfo = &swapped[cSwapped];
3971 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3975 if (ret && point->OnlySomeReasonFlags.cbData)
3977 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3978 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3979 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3980 items[cItem].pvStructInfo = &swapped[cSwapped];
3981 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3985 if (ret && point->fIndirectCRL)
3987 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3988 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3989 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3990 items[cItem].pvStructInfo = &swapped[cSwapped];
3991 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3996 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3997 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4001 SetLastError(STATUS_ACCESS_VIOLATION);
4008 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
4009 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4010 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4013 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4014 struct AsnEncodeSequenceItem items[3] = {
4015 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
4018 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4019 DWORD cItem = 1, cSwapped = 0;
4021 if (subtree->dwMinimum)
4023 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4024 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
4025 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4026 items[cItem].pvStructInfo = &swapped[cSwapped];
4027 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4031 if (subtree->fMaximum)
4033 swapped[cSwapped].tag = ASN_CONTEXT | 1;
4034 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
4035 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4036 items[cItem].pvStructInfo = &swapped[cSwapped];
4037 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4041 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
4042 pEncodePara, pbEncoded, pcbEncoded);
4046 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
4047 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4048 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4051 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
4053 TRACE("%p\n", pvStructInfo);
4057 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4058 struct AsnEncodeSequenceItem items[2] = { { 0 } };
4059 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4060 DWORD i, cItem = 0, cSwapped = 0;
4063 if (constraints->cPermittedSubtree)
4065 permitted.rgBlob = CryptMemAlloc(
4066 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4067 if (permitted.rgBlob)
4069 permitted.cBlob = constraints->cPermittedSubtree;
4070 memset(permitted.rgBlob, 0,
4071 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4072 for (i = 0; ret && i < permitted.cBlob; i++)
4073 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4074 NULL, &constraints->rgPermittedSubtree[i],
4075 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4076 (BYTE *)&permitted.rgBlob[i].pbData,
4077 &permitted.rgBlob[i].cbData);
4080 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4081 swapped[cSwapped].pvStructInfo = &permitted;
4082 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4083 items[cItem].pvStructInfo = &swapped[cSwapped];
4084 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4092 if (constraints->cExcludedSubtree)
4094 excluded.rgBlob = CryptMemAlloc(
4095 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4096 if (excluded.rgBlob)
4098 excluded.cBlob = constraints->cExcludedSubtree;
4099 memset(excluded.rgBlob, 0,
4100 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4101 for (i = 0; ret && i < excluded.cBlob; i++)
4102 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4103 NULL, &constraints->rgExcludedSubtree[i],
4104 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4105 (BYTE *)&excluded.rgBlob[i].pbData,
4106 &excluded.rgBlob[i].cbData);
4109 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4110 swapped[cSwapped].pvStructInfo = &excluded;
4111 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4112 items[cItem].pvStructInfo = &swapped[cSwapped];
4113 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4122 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4123 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4124 for (i = 0; i < permitted.cBlob; i++)
4125 LocalFree(permitted.rgBlob[i].pbData);
4126 for (i = 0; i < excluded.cBlob; i++)
4127 LocalFree(excluded.rgBlob[i].pbData);
4131 SetLastError(STATUS_ACCESS_VIOLATION);
4134 CryptMemFree(permitted.rgBlob);
4135 CryptMemFree(excluded.rgBlob);
4136 TRACE("returning %d\n", ret);
4140 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4141 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4142 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4146 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4147 struct AsnEncodeSequenceItem items[] = {
4148 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
4149 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4152 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4153 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4158 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4159 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4160 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4164 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4166 SetLastError(E_INVALIDARG);
4172 const CMSG_SIGNER_INFO *info = pvStructInfo;
4174 if (!info->Issuer.cbData)
4175 SetLastError(E_INVALIDARG);
4178 struct AsnEncodeSequenceItem items[7] = {
4179 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4180 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4181 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4184 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4185 DWORD cItem = 3, cSwapped = 0;
4187 if (info->AuthAttrs.cAttr)
4189 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4190 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4191 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4192 items[cItem].pvStructInfo = &swapped[cSwapped];
4193 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4197 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4198 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4200 items[cItem].pvStructInfo = &info->EncryptedHash;
4201 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4203 if (info->UnauthAttrs.cAttr)
4205 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4206 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4207 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4208 items[cItem].pvStructInfo = &swapped[cSwapped];
4209 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4213 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4214 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4219 SetLastError(STATUS_ACCESS_VIOLATION);
4225 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4226 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4227 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4231 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4233 SetLastError(E_INVALIDARG);
4239 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4241 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4242 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4243 SetLastError(E_INVALIDARG);
4244 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4245 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4246 SetLastError(E_INVALIDARG);
4249 struct AsnEncodeSequenceItem items[7] = {
4250 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4252 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4253 DWORD cItem = 1, cSwapped = 0;
4255 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4257 items[cItem].pvStructInfo =
4258 &info->SignerId.u.IssuerSerialNumber.Issuer;
4259 items[cItem].encodeFunc =
4260 CRYPT_AsnEncodeIssuerSerialNumber;
4265 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4266 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4267 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4268 items[cItem].pvStructInfo = &swapped[cSwapped];
4269 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4273 items[cItem].pvStructInfo = &info->HashAlgorithm;
4274 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4276 if (info->AuthAttrs.cAttr)
4278 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4279 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4280 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4281 items[cItem].pvStructInfo = &swapped[cSwapped];
4282 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4286 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4287 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4289 items[cItem].pvStructInfo = &info->EncryptedHash;
4290 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4292 if (info->UnauthAttrs.cAttr)
4294 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4295 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4296 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4297 items[cItem].pvStructInfo = &swapped[cSwapped];
4298 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4302 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4303 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4308 SetLastError(STATUS_ACCESS_VIOLATION);
4314 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4317 struct AsnEncodeSequenceItem items[7] = {
4318 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4320 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4321 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4322 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4323 DWORD cItem = 1, cSwapped = 0;
4326 if (signedInfo->cSignerInfo)
4328 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4329 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4330 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4331 digestAlgorithmsSet.itemOffset =
4332 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4333 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4334 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4335 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4338 items[cItem].pvStructInfo = &signedInfo->content;
4339 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4341 if (signedInfo->cCertEncoded)
4343 certSet.cItems = signedInfo->cCertEncoded;
4344 certSet.items = signedInfo->rgCertEncoded;
4345 certSet.itemSize = sizeof(CERT_BLOB);
4346 certSet.itemOffset = 0;
4347 certSet.encode = CRYPT_CopyEncodedBlob;
4348 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4349 swapped[cSwapped].pvStructInfo = &certSet;
4350 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4351 items[cItem].pvStructInfo = &swapped[cSwapped];
4352 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4356 if (signedInfo->cCrlEncoded)
4358 crlSet.cItems = signedInfo->cCrlEncoded;
4359 crlSet.items = signedInfo->rgCrlEncoded;
4360 crlSet.itemSize = sizeof(CRL_BLOB);
4361 crlSet.itemOffset = 0;
4362 crlSet.encode = CRYPT_CopyEncodedBlob;
4363 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4364 swapped[cSwapped].pvStructInfo = &crlSet;
4365 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4366 items[cItem].pvStructInfo = &swapped[cSwapped];
4367 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4371 if (ret && signedInfo->cSignerInfo)
4373 signerSet.cItems = signedInfo->cSignerInfo;
4374 signerSet.items = signedInfo->rgSignerInfo;
4375 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4376 signerSet.itemOffset = 0;
4377 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4378 items[cItem].pvStructInfo = &signerSet;
4379 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4383 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4384 items, cItem, 0, NULL, pvData, pcbData);
4389 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
4390 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4391 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4393 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
4394 struct AsnEncodeSequenceItem items[] = {
4395 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4396 { &info->RecipientId.u.IssuerSerialNumber,
4397 CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4398 { &info->KeyEncryptionAlgorithm,
4399 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4400 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
4403 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4404 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4408 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
4409 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4410 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4412 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
4413 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
4414 &info->encryptedContent, CRYPT_AsnEncodeOctets };
4415 struct AsnEncodeSequenceItem items[] = {
4416 { info->contentType, CRYPT_AsnEncodeOid, 0 },
4417 { &info->contentEncryptionAlgorithm,
4418 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4419 { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
4422 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4423 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4427 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
4428 void *pvData, DWORD *pcbData)
4430 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
4431 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
4432 CRYPT_AsnEncodeRecipientInfo };
4433 struct AsnEncodeSequenceItem items[] = {
4434 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
4435 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
4436 { &envelopedData->encryptedContentInfo,
4437 CRYPT_AsnEncodeEncryptedContentInfo, 0 },
4440 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
4441 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
4444 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4445 LPCSTR lpszStructType)
4447 CryptEncodeObjectExFunc encodeFunc = NULL;
4449 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4450 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4452 SetLastError(ERROR_FILE_NOT_FOUND);
4456 if (IS_INTOID(lpszStructType))
4458 switch (LOWORD(lpszStructType))
4460 case LOWORD(X509_CERT):
4461 encodeFunc = CRYPT_AsnEncodeCert;
4463 case LOWORD(X509_CERT_TO_BE_SIGNED):
4464 encodeFunc = CRYPT_AsnEncodeCertInfo;
4466 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4467 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4469 case LOWORD(X509_EXTENSIONS):
4470 encodeFunc = CRYPT_AsnEncodeExtensions;
4472 case LOWORD(X509_NAME_VALUE):
4473 encodeFunc = CRYPT_AsnEncodeNameValue;
4475 case LOWORD(X509_NAME):
4476 encodeFunc = CRYPT_AsnEncodeName;
4478 case LOWORD(X509_PUBLIC_KEY_INFO):
4479 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4481 case LOWORD(X509_AUTHORITY_KEY_ID):
4482 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4484 case LOWORD(X509_ALTERNATE_NAME):
4485 encodeFunc = CRYPT_AsnEncodeAltName;
4487 case LOWORD(X509_BASIC_CONSTRAINTS):
4488 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4490 case LOWORD(X509_BASIC_CONSTRAINTS2):
4491 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4493 case LOWORD(X509_CERT_POLICIES):
4494 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4496 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4497 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4499 case LOWORD(X509_UNICODE_NAME):
4500 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4502 case LOWORD(PKCS_CONTENT_INFO):
4503 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4505 case LOWORD(PKCS_ATTRIBUTE):
4506 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4508 case LOWORD(X509_UNICODE_NAME_VALUE):
4509 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4511 case LOWORD(X509_OCTET_STRING):
4512 encodeFunc = CRYPT_AsnEncodeOctets;
4514 case LOWORD(X509_BITS):
4515 case LOWORD(X509_KEY_USAGE):
4516 encodeFunc = CRYPT_AsnEncodeBits;
4518 case LOWORD(X509_INTEGER):
4519 encodeFunc = CRYPT_AsnEncodeInt;
4521 case LOWORD(X509_MULTI_BYTE_INTEGER):
4522 encodeFunc = CRYPT_AsnEncodeInteger;
4524 case LOWORD(X509_MULTI_BYTE_UINT):
4525 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4527 case LOWORD(X509_ENUMERATED):
4528 encodeFunc = CRYPT_AsnEncodeEnumerated;
4530 case LOWORD(X509_CHOICE_OF_TIME):
4531 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4533 case LOWORD(X509_AUTHORITY_KEY_ID2):
4534 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4536 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4537 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4539 case LOWORD(X509_SEQUENCE_OF_ANY):
4540 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4542 case LOWORD(PKCS_UTC_TIME):
4543 encodeFunc = CRYPT_AsnEncodeUtcTime;
4545 case LOWORD(X509_CRL_DIST_POINTS):
4546 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4548 case LOWORD(X509_ENHANCED_KEY_USAGE):
4549 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4551 case LOWORD(PKCS_CTL):
4552 encodeFunc = CRYPT_AsnEncodeCTL;
4554 case LOWORD(PKCS_SMIME_CAPABILITIES):
4555 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4557 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4558 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4560 case LOWORD(PKCS_ATTRIBUTES):
4561 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4563 case LOWORD(X509_ISSUING_DIST_POINT):
4564 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4566 case LOWORD(X509_NAME_CONSTRAINTS):
4567 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4569 case LOWORD(X509_POLICY_MAPPINGS):
4570 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4572 case LOWORD(X509_POLICY_CONSTRAINTS):
4573 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4575 case LOWORD(PKCS7_SIGNER_INFO):
4576 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4578 case LOWORD(CMS_SIGNER_INFO):
4579 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4583 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4584 encodeFunc = CRYPT_AsnEncodeExtensions;
4585 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4586 encodeFunc = CRYPT_AsnEncodeUtcTime;
4587 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4588 encodeFunc = CRYPT_AsnEncodeUtcTime;
4589 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4590 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4591 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4592 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4593 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4594 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4595 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4596 encodeFunc = CRYPT_AsnEncodeEnumerated;
4597 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4598 encodeFunc = CRYPT_AsnEncodeBits;
4599 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4600 encodeFunc = CRYPT_AsnEncodeOctets;
4601 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4602 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4603 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4604 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4605 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4606 encodeFunc = CRYPT_AsnEncodeAltName;
4607 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4608 encodeFunc = CRYPT_AsnEncodeAltName;
4609 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4610 encodeFunc = CRYPT_AsnEncodeAltName;
4611 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4612 encodeFunc = CRYPT_AsnEncodeAltName;
4613 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4614 encodeFunc = CRYPT_AsnEncodeAltName;
4615 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4616 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4617 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4618 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4619 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4620 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4621 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4622 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4623 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4624 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4625 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4626 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4627 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4628 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4629 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4630 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4631 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4632 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4633 else if (!strcmp(lpszStructType, szOID_CTL))
4634 encodeFunc = CRYPT_AsnEncodeCTL;
4638 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4639 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4641 static HCRYPTOIDFUNCSET set = NULL;
4642 CryptEncodeObjectFunc encodeFunc = NULL;
4645 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4646 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4647 (void **)&encodeFunc, hFunc);
4651 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4652 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4654 static HCRYPTOIDFUNCSET set = NULL;
4655 CryptEncodeObjectExFunc encodeFunc = NULL;
4658 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4659 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4660 (void **)&encodeFunc, hFunc);
4664 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4665 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4668 HCRYPTOIDFUNCADDR hFunc = NULL;
4669 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4670 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4672 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4673 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4676 if (!pbEncoded && !pcbEncoded)
4678 SetLastError(ERROR_INVALID_PARAMETER);
4682 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4685 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4686 debugstr_a(lpszStructType));
4687 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4688 lpszStructType, &hFunc);
4689 if (!pCryptEncodeObject)
4690 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4691 lpszStructType, &hFunc);
4693 if (pCryptEncodeObject)
4694 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4695 pvStructInfo, pbEncoded, pcbEncoded);
4696 else if (pCryptEncodeObjectEx)
4697 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4698 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4700 CryptFreeOIDFunctionAddress(hFunc, 0);
4701 TRACE_(crypt)("returning %d\n", ret);
4705 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4706 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4707 void *pvEncoded, DWORD *pcbEncoded)
4710 HCRYPTOIDFUNCADDR hFunc = NULL;
4711 CryptEncodeObjectExFunc encodeFunc = NULL;
4713 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4714 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4715 pvEncoded, pcbEncoded);
4717 if (!pvEncoded && !pcbEncoded)
4719 SetLastError(ERROR_INVALID_PARAMETER);
4723 SetLastError(NOERROR);
4724 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
4726 SetLastError(ERROR_INVALID_PARAMETER);
4729 *(BYTE **)pvEncoded = NULL;
4731 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4734 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4735 debugstr_a(lpszStructType));
4736 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4740 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4741 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4744 CryptEncodeObjectFunc pCryptEncodeObject =
4745 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4747 if (pCryptEncodeObject)
4749 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4751 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4752 pvStructInfo, NULL, pcbEncoded);
4753 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4754 pvEncoded, pcbEncoded, *pcbEncoded)))
4755 ret = pCryptEncodeObject(dwCertEncodingType,
4756 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4760 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4761 pvStructInfo, pvEncoded, pcbEncoded);
4765 CryptFreeOIDFunctionAddress(hFunc, 0);
4766 TRACE_(crypt)("returning %d\n", ret);
4770 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4771 LPCWSTR szPassword, DWORD dwFlags)
4773 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4776 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4777 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4779 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4780 pvReserved, dwFlags);
4784 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4785 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4787 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4788 NULL, 0, NULL, pInfo, pcbInfo);
4791 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4792 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4793 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4797 static CHAR oid[] = szOID_RSA_RSA;
4799 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4800 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4801 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4803 if (!pszPublicKeyObjId)
4804 pszPublicKeyObjId = oid;
4805 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4809 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4812 LPBYTE pubKey = CryptMemAlloc(keySize);
4816 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4820 DWORD encodedLen = 0;
4822 ret = CryptEncodeObject(dwCertEncodingType,
4823 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4826 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4827 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4830 *pcbInfo = sizeNeeded;
4831 else if (*pcbInfo < sizeNeeded)
4833 SetLastError(ERROR_MORE_DATA);
4834 *pcbInfo = sizeNeeded;
4839 *pcbInfo = sizeNeeded;
4840 pInfo->Algorithm.pszObjId = (char *)pInfo +
4841 sizeof(CERT_PUBLIC_KEY_INFO);
4842 lstrcpyA(pInfo->Algorithm.pszObjId,
4844 pInfo->Algorithm.Parameters.cbData = 0;
4845 pInfo->Algorithm.Parameters.pbData = NULL;
4846 pInfo->PublicKey.pbData =
4847 (BYTE *)pInfo->Algorithm.pszObjId
4848 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4849 pInfo->PublicKey.cbData = encodedLen;
4850 pInfo->PublicKey.cUnusedBits = 0;
4851 ret = CryptEncodeObject(dwCertEncodingType,
4852 RSA_CSP_PUBLICKEYBLOB, pubKey,
4853 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4857 CryptMemFree(pubKey);
4862 CryptDestroyKey(key);
4867 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4868 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4869 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4871 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4872 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4873 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4875 static HCRYPTOIDFUNCSET set = NULL;
4877 ExportPublicKeyInfoExFunc exportFunc = NULL;
4878 HCRYPTOIDFUNCADDR hFunc = NULL;
4880 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4881 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4882 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4886 SetLastError(ERROR_INVALID_PARAMETER);
4890 if (pszPublicKeyObjId)
4893 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4895 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4896 0, (void **)&exportFunc, &hFunc);
4899 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4900 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4901 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4903 CryptFreeOIDFunctionAddress(hFunc, 0);
4907 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4908 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4910 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4914 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4915 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4916 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4919 DWORD pubKeySize = 0;
4921 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4922 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4924 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4925 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4928 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4932 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4933 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4938 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4939 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4942 CryptMemFree(pubKey);
4950 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4951 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4952 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4954 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4955 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4956 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4958 static HCRYPTOIDFUNCSET set = NULL;
4960 ImportPublicKeyInfoExFunc importFunc = NULL;
4961 HCRYPTOIDFUNCADDR hFunc = NULL;
4963 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4964 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4967 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4968 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4969 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4971 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4972 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4975 CryptFreeOIDFunctionAddress(hFunc, 0);