2 * Copyright 2005 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 is
21 * undocumented, 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
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "wine/unicode.h"
48 #include "crypt32_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
55 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
56 * The dwCertEncodingType and lpszStructType are ignored by the built-in
57 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
58 * since it must call functions in external DLLs that follow these signatures.
60 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
61 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
62 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
63 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
64 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
65 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
66 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
67 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
68 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
69 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
70 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
71 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
72 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
73 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
74 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
75 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
77 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
78 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
80 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
81 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
82 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
83 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
84 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
86 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
87 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
88 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
89 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
90 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
92 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
95 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
97 static HCRYPTOIDFUNCSET set = NULL;
99 HCRYPTOIDFUNCADDR hFunc;
100 CryptEncodeObjectFunc pCryptEncodeObject;
102 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
103 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
106 if (!pbEncoded && !pcbEncoded)
108 SetLastError(ERROR_INVALID_PARAMETER);
112 /* Try registered DLL first.. */
114 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
115 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
116 (void **)&pCryptEncodeObject, &hFunc);
117 if (pCryptEncodeObject)
119 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
120 pvStructInfo, pbEncoded, pcbEncoded);
121 CryptFreeOIDFunctionAddress(hFunc, 0);
125 /* If not, use CryptEncodeObjectEx */
126 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
127 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
132 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
133 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
137 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
139 if (pEncodePara && pEncodePara->pfnAlloc)
140 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
142 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
143 if (!*(BYTE **)pbEncoded)
146 *pcbEncoded = bytesNeeded;
148 else if (bytesNeeded > *pcbEncoded)
150 *pcbEncoded = bytesNeeded;
151 SetLastError(ERROR_MORE_DATA);
155 *pcbEncoded = bytesNeeded;
159 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
161 DWORD bytesNeeded, significantBytes = 0;
169 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
170 temp <<= 8, significantBytes--)
172 bytesNeeded = significantBytes + 1;
176 *pcbEncoded = bytesNeeded;
179 if (*pcbEncoded < bytesNeeded)
181 SetLastError(ERROR_MORE_DATA);
185 *pbEncoded = (BYTE)len;
190 *pbEncoded++ = significantBytes | 0x80;
191 for (i = 0; i < significantBytes; i++)
193 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
197 *pcbEncoded = bytesNeeded;
201 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
202 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
206 DWORD i, dataLen = 0;
208 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
209 pbEncoded, *pcbEncoded);
210 for (i = 0, ret = TRUE; ret && i < cItem; i++)
212 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
213 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
214 NULL, &items[i].size);
215 /* Some functions propagate their errors through the size */
217 *pcbEncoded = items[i].size;
218 dataLen += items[i].size;
222 DWORD lenBytes, bytesNeeded;
224 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
225 bytesNeeded = 1 + lenBytes + dataLen;
227 *pcbEncoded = bytesNeeded;
230 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
231 pcbEncoded, bytesNeeded)))
233 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
234 pbEncoded = *(BYTE **)pbEncoded;
235 *pbEncoded++ = ASN_SEQUENCE;
236 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
237 pbEncoded += lenBytes;
238 for (i = 0; ret && i < cItem; i++)
240 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
241 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
242 NULL, pbEncoded, &items[i].size);
243 /* Some functions propagate their errors through the size */
245 *pcbEncoded = items[i].size;
246 pbEncoded += items[i].size;
251 TRACE("returning %d (%08x)\n", ret, GetLastError());
255 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
256 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
257 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
260 const struct AsnConstructedItem *item =
261 (const struct AsnConstructedItem *)pvStructInfo;
264 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
265 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
267 DWORD dataLen, bytesNeeded;
269 CRYPT_EncodeLen(len, NULL, &dataLen);
270 bytesNeeded = 1 + dataLen + len;
272 *pcbEncoded = bytesNeeded;
273 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
274 pbEncoded, pcbEncoded, bytesNeeded)))
276 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
277 pbEncoded = *(BYTE **)pbEncoded;
278 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
279 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
280 pbEncoded += dataLen;
281 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
282 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
286 /* Some functions propagate their errors through the size */
293 /* Some functions propagate their errors through the size */
299 struct AsnEncodeTagSwappedItem
302 const void *pvStructInfo;
303 CryptEncodeObjectExFunc encodeFunc;
306 /* Sort of a wacky hack, it encodes something using the struct
307 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
308 * given in the struct AsnEncodeTagSwappedItem.
310 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
311 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
312 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
315 const struct AsnEncodeTagSwappedItem *item =
316 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
318 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
319 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
320 if (ret && pbEncoded)
321 *pbEncoded = item->tag;
325 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
326 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
327 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
329 const DWORD *ver = (const DWORD *)pvStructInfo;
332 /* CERT_V1 is not encoded */
340 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
342 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
343 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
348 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
349 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
350 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
352 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
357 *pcbEncoded = blob->cbData;
362 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
363 pcbEncoded, blob->cbData)))
365 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
366 pbEncoded = *(BYTE **)pbEncoded;
368 memcpy(pbEncoded, blob->pbData, blob->cbData);
369 *pcbEncoded = blob->cbData;
376 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
377 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
378 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
381 /* This has two filetimes in a row, a NotBefore and a NotAfter */
382 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
383 struct AsnEncodeSequenceItem items[] = {
384 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
385 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
388 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
389 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
394 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
397 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
398 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
399 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
402 const CRYPT_ALGORITHM_IDENTIFIER *algo =
403 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
404 static const BYTE asn1Null[] = { ASN_NULL, 0 };
405 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
408 struct AsnEncodeSequenceItem items[2] = {
409 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
410 { NULL, CRYPT_CopyEncodedBlob, 0 },
413 if (algo->Parameters.cbData)
414 items[1].pvStructInfo = &algo->Parameters;
416 items[1].pvStructInfo = &nullBlob;
417 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
418 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
423 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(DWORD dwCertEncodingType,
424 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
425 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
427 const CRYPT_ALGORITHM_IDENTIFIER *algo =
428 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
430 struct AsnEncodeSequenceItem items[] = {
431 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
432 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
435 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
436 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
441 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
442 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
443 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
449 const CERT_PUBLIC_KEY_INFO *info =
450 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
451 struct AsnEncodeSequenceItem items[] = {
452 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
453 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
456 TRACE("Encoding public key with OID %s\n",
457 debugstr_a(info->Algorithm.pszObjId));
458 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
459 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
464 SetLastError(STATUS_ACCESS_VIOLATION);
471 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
473 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
479 const CERT_SIGNED_CONTENT_INFO *info =
480 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
481 struct AsnEncodeSequenceItem items[] = {
482 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
483 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
484 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
487 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
488 items[2].encodeFunc = CRYPT_AsnEncodeBits;
489 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
490 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
495 SetLastError(STATUS_ACCESS_VIOLATION);
502 /* Like in Windows, this blithely ignores the validity of the passed-in
503 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
504 * decode properly, see CRYPT_AsnDecodeCertInfo.
506 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
507 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
508 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
514 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
515 struct AsnEncodeSequenceItem items[10] = {
516 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
517 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
518 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
519 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
520 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
521 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
522 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
525 struct AsnConstructedItem constructed[3] = { { 0 } };
526 DWORD cItem = 7, cConstructed = 0;
528 if (info->IssuerUniqueId.cbData)
530 constructed[cConstructed].tag = 1;
531 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
532 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
533 items[cItem].pvStructInfo = &constructed[cConstructed];
534 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
538 if (info->SubjectUniqueId.cbData)
540 constructed[cConstructed].tag = 2;
541 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
542 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
543 items[cItem].pvStructInfo = &constructed[cConstructed];
544 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
548 if (info->cExtension)
550 constructed[cConstructed].tag = 3;
551 constructed[cConstructed].pvStructInfo = &info->cExtension;
552 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
553 items[cItem].pvStructInfo = &constructed[cConstructed];
554 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
559 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
560 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
564 SetLastError(STATUS_ACCESS_VIOLATION);
571 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
572 BYTE *pbEncoded, DWORD *pcbEncoded)
574 struct AsnEncodeSequenceItem items[3] = {
575 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
576 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
582 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
584 if (entry->cExtension)
586 items[cItem].pvStructInfo = &entry->cExtension;
587 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
591 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
592 pbEncoded, pcbEncoded);
594 TRACE("returning %d (%08x)\n", ret, GetLastError());
598 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
599 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
600 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
602 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
603 DWORD bytesNeeded, dataLen, lenBytes, i;
604 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
605 ((const BYTE *)pvStructInfo + sizeof(DWORD));
608 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
616 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
617 bytesNeeded = 1 + lenBytes + dataLen;
619 *pcbEncoded = bytesNeeded;
622 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
623 pcbEncoded, bytesNeeded)))
625 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
626 pbEncoded = *(BYTE **)pbEncoded;
627 *pbEncoded++ = ASN_SEQUENCEOF;
628 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
629 pbEncoded += lenBytes;
630 for (i = 0; i < cCRLEntry; i++)
632 DWORD size = dataLen;
634 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
643 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
644 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
645 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
647 const DWORD *ver = (const DWORD *)pvStructInfo;
650 /* CRL_V1 is not encoded */
657 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
658 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
662 /* Like in Windows, this blithely ignores the validity of the passed-in
663 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
664 * decode properly, see CRYPT_AsnDecodeCRLInfo.
666 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
667 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
668 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
674 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
675 struct AsnEncodeSequenceItem items[7] = {
676 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
677 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
678 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
679 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
682 struct AsnConstructedItem constructed[1] = { { 0 } };
683 DWORD cItem = 4, cConstructed = 0;
685 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
687 items[cItem].pvStructInfo = &info->NextUpdate;
688 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
693 items[cItem].pvStructInfo = &info->cCRLEntry;
694 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
697 if (info->cExtension)
699 constructed[cConstructed].tag = 0;
700 constructed[cConstructed].pvStructInfo = &info->cExtension;
701 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
702 items[cItem].pvStructInfo = &constructed[cConstructed];
703 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
708 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
709 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
713 SetLastError(STATUS_ACCESS_VIOLATION);
720 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
724 struct AsnEncodeSequenceItem items[3] = {
725 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
731 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
735 items[cItem].pvStructInfo = &ext->fCritical;
736 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
739 items[cItem].pvStructInfo = &ext->Value;
740 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
743 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
744 pbEncoded, pcbEncoded);
745 TRACE("returning %d (%08x)\n", ret, GetLastError());
749 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
750 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
751 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
757 DWORD bytesNeeded, dataLen, lenBytes, i;
758 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
761 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
765 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
769 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
770 bytesNeeded = 1 + lenBytes + dataLen;
772 *pcbEncoded = bytesNeeded;
775 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
776 pcbEncoded, bytesNeeded)))
778 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
779 pbEncoded = *(BYTE **)pbEncoded;
780 *pbEncoded++ = ASN_SEQUENCEOF;
781 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
782 pbEncoded += lenBytes;
783 for (i = 0; i < exts->cExtension; i++)
785 DWORD size = dataLen;
787 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
797 SetLastError(STATUS_ACCESS_VIOLATION);
804 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
805 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
806 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
808 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
809 DWORD bytesNeeded = 0, lenBytes;
814 TRACE("%s\n", debugstr_a(pszObjId));
821 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
823 SetLastError(CRYPT_E_ASN1_ERROR);
827 firstByte = val1 * 40 + val2;
828 ptr = pszObjId + firstPos;
833 /* note I assume each component is at most 32-bits long in base 2 */
834 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
836 if (val1 >= 0x10000000)
838 else if (val1 >= 0x200000)
840 else if (val1 >= 0x4000)
842 else if (val1 >= 0x80)
852 SetLastError(CRYPT_E_ASN1_ERROR);
856 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
860 bytesNeeded += 1 + lenBytes;
863 if (*pcbEncoded < bytesNeeded)
865 SetLastError(ERROR_MORE_DATA);
870 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
871 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
872 pbEncoded += lenBytes;
878 *pbEncoded++ = firstByte;
879 ptr = pszObjId + firstPos;
882 sscanf(ptr, "%d%n", &val, &pos);
884 unsigned char outBytes[5];
887 if (val >= 0x10000000)
889 else if (val >= 0x200000)
891 else if (val >= 0x4000)
893 else if (val >= 0x80)
897 for (i = numBytes; i > 0; i--)
899 outBytes[i - 1] = val & 0x7f;
902 for (i = 0; i < numBytes - 1; i++)
903 *pbEncoded++ = outBytes[i] | 0x80;
904 *pbEncoded++ = outBytes[i];
913 *pcbEncoded = bytesNeeded;
917 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
918 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
922 LPCSTR str = (LPCSTR)value->Value.pbData;
923 DWORD bytesNeeded, lenBytes, encodedLen;
925 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
926 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
927 bytesNeeded = 1 + lenBytes + encodedLen;
929 *pcbEncoded = bytesNeeded;
932 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
933 pbEncoded, pcbEncoded, bytesNeeded)))
935 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
936 pbEncoded = *(BYTE **)pbEncoded;
938 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
939 pbEncoded += lenBytes;
940 memcpy(pbEncoded, str, encodedLen);
946 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
947 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
951 LPCWSTR str = (LPCWSTR)value->Value.pbData;
952 DWORD bytesNeeded, lenBytes, strLen;
954 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
956 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
957 bytesNeeded = 1 + lenBytes + strLen * 2;
959 *pcbEncoded = bytesNeeded;
962 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
963 pbEncoded, pcbEncoded, bytesNeeded)))
967 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
968 pbEncoded = *(BYTE **)pbEncoded;
969 *pbEncoded++ = ASN_BMPSTRING;
970 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
971 pbEncoded += lenBytes;
972 for (i = 0; i < strLen; i++)
974 *pbEncoded++ = (str[i] & 0xff00) >> 8;
975 *pbEncoded++ = str[i] & 0x00ff;
982 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
983 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
987 LPCWSTR str = (LPCWSTR)value->Value.pbData;
988 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
990 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
992 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
994 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
995 bytesNeeded = 1 + lenBytes + encodedLen;
997 *pcbEncoded = bytesNeeded;
1000 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1001 pbEncoded, pcbEncoded, bytesNeeded)))
1003 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1004 pbEncoded = *(BYTE **)pbEncoded;
1005 *pbEncoded++ = ASN_UTF8STRING;
1006 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1007 pbEncoded += lenBytes;
1008 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1009 bytesNeeded - lenBytes - 1, NULL, NULL);
1015 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1016 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1017 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1023 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1025 switch (value->dwValueType)
1027 case CERT_RDN_ANY_TYPE:
1028 /* explicitly disallowed */
1029 SetLastError(E_INVALIDARG);
1032 case CERT_RDN_ENCODED_BLOB:
1033 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1034 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1036 case CERT_RDN_OCTET_STRING:
1037 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1038 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1040 case CERT_RDN_NUMERIC_STRING:
1041 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1042 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1044 case CERT_RDN_PRINTABLE_STRING:
1045 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1046 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1048 case CERT_RDN_TELETEX_STRING:
1049 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1050 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1052 case CERT_RDN_VIDEOTEX_STRING:
1053 ret = CRYPT_AsnEncodeStringCoerce(value,
1054 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1056 case CERT_RDN_IA5_STRING:
1057 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1058 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1060 case CERT_RDN_GRAPHIC_STRING:
1061 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1062 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1064 case CERT_RDN_VISIBLE_STRING:
1065 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1066 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1068 case CERT_RDN_GENERAL_STRING:
1069 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1070 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1072 case CERT_RDN_UNIVERSAL_STRING:
1073 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1074 SetLastError(CRYPT_E_ASN1_CHOICE);
1077 case CERT_RDN_BMP_STRING:
1078 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1079 pbEncoded, pcbEncoded);
1081 case CERT_RDN_UTF8_STRING:
1082 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1083 pbEncoded, pcbEncoded);
1086 SetLastError(CRYPT_E_ASN1_CHOICE);
1092 SetLastError(STATUS_ACCESS_VIOLATION);
1099 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1100 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1101 BYTE *pbEncoded, DWORD *pcbEncoded)
1103 DWORD bytesNeeded = 0, lenBytes, size;
1106 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1107 0, NULL, NULL, &size);
1110 bytesNeeded += size;
1111 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1112 * with dwValueType, so "cast" it to get its encoded size
1114 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1115 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1118 bytesNeeded += size;
1119 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1120 bytesNeeded += 1 + lenBytes;
1123 if (*pcbEncoded < bytesNeeded)
1125 SetLastError(ERROR_MORE_DATA);
1130 *pbEncoded++ = ASN_SEQUENCE;
1131 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1133 pbEncoded += lenBytes;
1134 size = bytesNeeded - 1 - lenBytes;
1135 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1136 attr->pszObjId, 0, NULL, pbEncoded, &size);
1140 size = bytesNeeded - 1 - lenBytes - size;
1141 ret = nameValueEncodeFunc(dwCertEncodingType,
1142 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1143 0, NULL, pbEncoded, &size);
1150 *pcbEncoded = bytesNeeded;
1154 /* Have to propagate index of failing character */
1161 static int BLOBComp(const void *l, const void *r)
1163 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1166 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1167 ret = a->cbData - b->cbData;
1171 typedef struct _CRYPT_SET_OF {
1173 PCRYPT_DER_BLOB rgValue;
1176 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1178 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1182 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1183 DWORD bytesNeeded = 0, lenBytes, i;
1186 for (i = 0; i < set->cValue; i++)
1187 bytesNeeded += set->rgValue[i].cbData;
1188 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1189 bytesNeeded += 1 + lenBytes;
1192 *pcbEncoded = bytesNeeded;
1195 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1196 pbEncoded, pcbEncoded, bytesNeeded)))
1198 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1199 pbEncoded = *(BYTE **)pbEncoded;
1200 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1201 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1202 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1203 pbEncoded += lenBytes;
1204 for (i = 0; ret && i < set->cValue; i++)
1206 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1207 pbEncoded += set->rgValue[i].cbData;
1213 struct DERSetDescriptor
1219 CryptEncodeObjectExFunc encode;
1222 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1223 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1224 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1226 const struct DERSetDescriptor *desc =
1227 (const struct DERSetDescriptor *)pvStructInfo;
1228 CRYPT_SET_OF setOf = { 0, NULL };
1234 setOf.rgValue = CryptMemAlloc(setOf.cValue * sizeof(CRYPT_DER_BLOB));
1239 setOf.cValue = desc->cItems;
1240 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1243 for (i = 0; ret && i < setOf.cValue; i++)
1245 ret = desc->encode(dwCertEncodingType, lpszStructType,
1246 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1247 0, NULL, NULL, &setOf.rgValue[i].cbData);
1250 setOf.rgValue[i].pbData = CryptMemAlloc(setOf.rgValue[i].cbData);
1251 if (!setOf.rgValue[i].pbData)
1254 ret = desc->encode(dwCertEncodingType, lpszStructType,
1255 (const BYTE *)desc->items + i * desc->itemSize +
1256 desc->itemOffset, 0, NULL, setOf.rgValue[i].pbData,
1257 &setOf.rgValue[i].cbData);
1259 /* Some functions propagate their errors through the size */
1261 *pcbEncoded = setOf.rgValue[i].cbData;
1265 DWORD bytesNeeded = 0, lenBytes;
1268 for (i = 0; i < setOf.cValue; i++)
1269 bytesNeeded += setOf.rgValue[i].cbData;
1270 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1271 bytesNeeded += 1 + lenBytes;
1273 *pcbEncoded = bytesNeeded;
1274 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1275 pbEncoded, pcbEncoded, bytesNeeded)))
1277 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1278 pbEncoded = *(BYTE **)pbEncoded;
1279 qsort(setOf.rgValue, setOf.cValue, sizeof(CRYPT_DER_BLOB),
1281 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1282 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1283 pbEncoded += lenBytes;
1284 for (i = 0; i < setOf.cValue; i++)
1286 memcpy(pbEncoded, setOf.rgValue[i].pbData,
1287 setOf.rgValue[i].cbData);
1288 pbEncoded += setOf.rgValue[i].cbData;
1292 for (i = 0; i < setOf.cValue; i++)
1293 CryptMemFree(setOf.rgValue[i].pbData);
1294 CryptMemFree(setOf.rgValue);
1298 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1299 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1303 CRYPT_SET_OF setOf = { 0, NULL };
1312 setOf.cValue = rdn->cRDNAttr;
1313 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1314 sizeof(CRYPT_DER_BLOB));
1318 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1320 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1322 setOf.rgValue[i].cbData = 0;
1323 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1324 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1327 setOf.rgValue[i].pbData =
1328 CryptMemAlloc(setOf.rgValue[i].cbData);
1329 if (!setOf.rgValue[i].pbData)
1332 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1333 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1334 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1338 /* Have to propagate index of failing character */
1339 *pcbEncoded = setOf.rgValue[i].cbData;
1343 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1344 pbEncoded, pcbEncoded);
1345 for (i = 0; i < setOf.cValue; i++)
1346 CryptMemFree(setOf.rgValue[i].pbData);
1350 SetLastError(STATUS_ACCESS_VIOLATION);
1354 CryptMemFree(setOf.rgValue);
1358 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1359 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1360 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1362 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1363 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1364 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1367 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1370 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1371 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1372 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1374 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1375 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1379 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1380 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1381 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1387 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1388 DWORD bytesNeeded = 0, lenBytes, size, i;
1390 TRACE("encoding name with %d RDNs\n", info->cRDN);
1392 for (i = 0; ret && i < info->cRDN; i++)
1394 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1395 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1397 bytesNeeded += size;
1401 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1402 bytesNeeded += 1 + lenBytes;
1406 *pcbEncoded = bytesNeeded;
1409 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1410 pbEncoded, pcbEncoded, bytesNeeded)))
1412 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1413 pbEncoded = *(BYTE **)pbEncoded;
1414 *pbEncoded++ = ASN_SEQUENCEOF;
1415 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1417 pbEncoded += lenBytes;
1418 for (i = 0; ret && i < info->cRDN; i++)
1421 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1422 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1427 bytesNeeded -= size;
1438 SetLastError(STATUS_ACCESS_VIOLATION);
1445 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1446 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1447 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1453 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1455 if (!attr->pszObjId)
1456 SetLastError(E_INVALIDARG);
1459 struct AsnEncodeSequenceItem items[2] = {
1460 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1461 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1464 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1465 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1471 SetLastError(STATUS_ACCESS_VIOLATION);
1477 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1478 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1479 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1485 const CRYPT_ATTRIBUTES *attributes =
1486 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1487 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1488 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1490 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1491 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1495 SetLastError(STATUS_ACCESS_VIOLATION);
1501 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1502 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1503 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1504 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1507 const CRYPT_CONTENT_INFO *info = (const CRYPT_CONTENT_INFO *)pvStructInfo;
1508 struct AsnEncodeSequenceItem items[2] = {
1509 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1512 struct AsnConstructedItem constructed = { 0 };
1515 if (info->Content.cbData)
1517 constructed.tag = 0;
1518 constructed.pvStructInfo = &info->Content;
1519 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1520 items[cItem].pvStructInfo = &constructed;
1521 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1524 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1525 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1528 BOOL CRYPT_AsnEncodePKCSDigestedData(CRYPT_DIGESTED_DATA *digestedData,
1529 void *pvData, DWORD *pcbData)
1531 struct AsnEncodeSequenceItem items[] = {
1532 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1533 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1535 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1536 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1539 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1540 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1543 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1544 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1545 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1551 const CRYPT_CONTENT_INFO *info =
1552 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1554 if (!info->pszObjId)
1555 SetLastError(E_INVALIDARG);
1557 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1558 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1563 SetLastError(STATUS_ACCESS_VIOLATION);
1569 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1570 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1574 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1575 DWORD bytesNeeded, lenBytes, encodedLen;
1577 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1579 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1580 bytesNeeded = 1 + lenBytes + encodedLen;
1582 *pcbEncoded = bytesNeeded;
1585 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1586 pbEncoded, pcbEncoded, bytesNeeded)))
1590 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1591 pbEncoded = *(BYTE **)pbEncoded;
1593 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1594 pbEncoded += lenBytes;
1595 for (i = 0; i < encodedLen; i++)
1596 *pbEncoded++ = (BYTE)str[i];
1602 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1603 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1607 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1608 DWORD bytesNeeded, lenBytes, encodedLen;
1610 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1612 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1613 bytesNeeded = 1 + lenBytes + encodedLen;
1615 *pcbEncoded = bytesNeeded;
1618 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1619 pbEncoded, pcbEncoded, bytesNeeded)))
1623 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1624 pbEncoded = *(BYTE **)pbEncoded;
1625 *pbEncoded++ = ASN_NUMERICSTRING;
1626 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1627 pbEncoded += lenBytes;
1628 for (i = 0; ret && i < encodedLen; i++)
1630 if (isdigitW(str[i]))
1631 *pbEncoded++ = (BYTE)str[i];
1635 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1644 static inline int isprintableW(WCHAR wc)
1646 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1647 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1648 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1651 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1652 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1656 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1657 DWORD bytesNeeded, lenBytes, encodedLen;
1659 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1661 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1662 bytesNeeded = 1 + lenBytes + encodedLen;
1664 *pcbEncoded = bytesNeeded;
1667 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1668 pbEncoded, pcbEncoded, bytesNeeded)))
1672 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1673 pbEncoded = *(BYTE **)pbEncoded;
1674 *pbEncoded++ = ASN_PRINTABLESTRING;
1675 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1676 pbEncoded += lenBytes;
1677 for (i = 0; ret && i < encodedLen; i++)
1679 if (isprintableW(str[i]))
1680 *pbEncoded++ = (BYTE)str[i];
1684 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1693 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1694 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1698 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1699 DWORD bytesNeeded, lenBytes, encodedLen;
1701 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1703 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1704 bytesNeeded = 1 + lenBytes + encodedLen;
1706 *pcbEncoded = bytesNeeded;
1709 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1710 pbEncoded, pcbEncoded, bytesNeeded)))
1714 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1715 pbEncoded = *(BYTE **)pbEncoded;
1716 *pbEncoded++ = ASN_IA5STRING;
1717 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1718 pbEncoded += lenBytes;
1719 for (i = 0; ret && i < encodedLen; i++)
1722 *pbEncoded++ = (BYTE)str[i];
1726 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1735 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1736 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1740 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1741 DWORD bytesNeeded, lenBytes, strLen;
1743 /* FIXME: doesn't handle composite characters */
1744 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1746 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1747 bytesNeeded = 1 + lenBytes + strLen * 4;
1749 *pcbEncoded = bytesNeeded;
1752 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1753 pbEncoded, pcbEncoded, bytesNeeded)))
1757 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1758 pbEncoded = *(BYTE **)pbEncoded;
1759 *pbEncoded++ = ASN_UNIVERSALSTRING;
1760 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1761 pbEncoded += lenBytes;
1762 for (i = 0; i < strLen; i++)
1766 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1767 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1774 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1775 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1776 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1782 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1784 switch (value->dwValueType)
1786 case CERT_RDN_ANY_TYPE:
1787 case CERT_RDN_ENCODED_BLOB:
1788 case CERT_RDN_OCTET_STRING:
1789 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1791 case CERT_RDN_NUMERIC_STRING:
1792 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1793 pbEncoded, pcbEncoded);
1795 case CERT_RDN_PRINTABLE_STRING:
1796 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1797 pbEncoded, pcbEncoded);
1799 case CERT_RDN_TELETEX_STRING:
1800 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1801 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1803 case CERT_RDN_VIDEOTEX_STRING:
1804 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1805 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1807 case CERT_RDN_IA5_STRING:
1808 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1809 pbEncoded, pcbEncoded);
1811 case CERT_RDN_GRAPHIC_STRING:
1812 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1813 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1815 case CERT_RDN_VISIBLE_STRING:
1816 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1817 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1819 case CERT_RDN_GENERAL_STRING:
1820 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1821 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1823 case CERT_RDN_UNIVERSAL_STRING:
1824 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1825 pbEncoded, pcbEncoded);
1827 case CERT_RDN_BMP_STRING:
1828 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1829 pbEncoded, pcbEncoded);
1831 case CERT_RDN_UTF8_STRING:
1832 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1833 pbEncoded, pcbEncoded);
1836 SetLastError(CRYPT_E_ASN1_CHOICE);
1841 SetLastError(STATUS_ACCESS_VIOLATION);
1847 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1848 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1849 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1855 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1856 DWORD bytesNeeded = 0, lenBytes, size, i;
1858 TRACE("encoding name with %d RDNs\n", info->cRDN);
1860 for (i = 0; ret && i < info->cRDN; i++)
1862 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1863 CRYPT_AsnEncodeNameValue, NULL, &size);
1865 bytesNeeded += size;
1867 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1868 bytesNeeded += 1 + lenBytes;
1872 *pcbEncoded = bytesNeeded;
1875 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1876 pbEncoded, pcbEncoded, bytesNeeded)))
1878 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1879 pbEncoded = *(BYTE **)pbEncoded;
1880 *pbEncoded++ = ASN_SEQUENCEOF;
1881 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1883 pbEncoded += lenBytes;
1884 for (i = 0; ret && i < info->cRDN; i++)
1887 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1888 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1893 bytesNeeded -= size;
1902 SetLastError(STATUS_ACCESS_VIOLATION);
1909 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1910 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1911 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1913 BOOL val = *(const BOOL *)pvStructInfo, ret;
1922 else if (*pcbEncoded < 3)
1925 SetLastError(ERROR_MORE_DATA);
1931 *pbEncoded++ = ASN_BOOL;
1933 *pbEncoded++ = val ? 0xff : 0;
1936 TRACE("returning %d (%08x)\n", ret, GetLastError());
1940 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1941 BYTE *pbEncoded, DWORD *pcbEncoded)
1947 switch (entry->dwAltNameChoice)
1949 case CERT_ALT_NAME_RFC822_NAME:
1950 case CERT_ALT_NAME_DNS_NAME:
1951 case CERT_ALT_NAME_URL:
1952 if (entry->u.pwszURL)
1956 /* Not + 1: don't encode the NULL-terminator */
1957 dataLen = lstrlenW(entry->u.pwszURL);
1958 for (i = 0; ret && i < dataLen; i++)
1960 if (entry->u.pwszURL[i] > 0x7f)
1962 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1971 case CERT_ALT_NAME_IP_ADDRESS:
1972 dataLen = entry->u.IPAddress.cbData;
1974 case CERT_ALT_NAME_REGISTERED_ID:
1975 /* FIXME: encode OID */
1976 case CERT_ALT_NAME_OTHER_NAME:
1977 case CERT_ALT_NAME_DIRECTORY_NAME:
1978 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1981 SetLastError(E_INVALIDARG);
1986 DWORD bytesNeeded, lenBytes;
1988 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1989 bytesNeeded = 1 + dataLen + lenBytes;
1991 *pcbEncoded = bytesNeeded;
1992 else if (*pcbEncoded < bytesNeeded)
1994 SetLastError(ERROR_MORE_DATA);
1995 *pcbEncoded = bytesNeeded;
2000 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2001 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2002 pbEncoded += lenBytes;
2003 switch (entry->dwAltNameChoice)
2005 case CERT_ALT_NAME_RFC822_NAME:
2006 case CERT_ALT_NAME_DNS_NAME:
2007 case CERT_ALT_NAME_URL:
2011 for (i = 0; i < dataLen; i++)
2012 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2015 case CERT_ALT_NAME_IP_ADDRESS:
2016 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2020 *pcbEncoded = bytesNeeded;
2023 TRACE("returning %d (%08x)\n", ret, GetLastError());
2027 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2028 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2029 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2035 const CERT_AUTHORITY_KEY_ID_INFO *info =
2036 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
2037 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2038 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2039 struct AsnConstructedItem constructed = { 0 };
2040 DWORD cItem = 0, cSwapped = 0;
2042 if (info->KeyId.cbData)
2044 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2045 swapped[cSwapped].pvStructInfo = &info->KeyId;
2046 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2047 items[cItem].pvStructInfo = &swapped[cSwapped];
2048 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2052 if (info->CertIssuer.cbData)
2054 constructed.tag = 1;
2055 constructed.pvStructInfo = &info->CertIssuer;
2056 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2057 items[cItem].pvStructInfo = &constructed;
2058 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2061 if (info->CertSerialNumber.cbData)
2063 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2064 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2065 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2066 items[cItem].pvStructInfo = &swapped[cSwapped];
2067 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2071 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2072 pEncodePara, pbEncoded, pcbEncoded);
2076 SetLastError(STATUS_ACCESS_VIOLATION);
2083 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2084 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2085 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2091 const CERT_ALT_NAME_INFO *info =
2092 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2093 DWORD bytesNeeded, dataLen, lenBytes, i;
2096 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2097 * can't encode an erroneous entry index if it's bigger than this.
2099 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2103 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2107 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2109 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2110 * the bad character, now set the index of the bad
2113 *pcbEncoded = (BYTE)i <<
2114 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2119 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2120 bytesNeeded = 1 + lenBytes + dataLen;
2123 *pcbEncoded = bytesNeeded;
2128 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2129 pbEncoded, pcbEncoded, bytesNeeded)))
2131 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2132 pbEncoded = *(BYTE **)pbEncoded;
2133 *pbEncoded++ = ASN_SEQUENCEOF;
2134 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2135 pbEncoded += lenBytes;
2136 for (i = 0; ret && i < info->cAltEntry; i++)
2138 DWORD len = dataLen;
2140 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2154 SetLastError(STATUS_ACCESS_VIOLATION);
2161 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2162 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2163 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2169 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2170 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2171 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2172 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2173 DWORD cItem = 0, cSwapped = 0;
2175 if (info->KeyId.cbData)
2177 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2178 swapped[cSwapped].pvStructInfo = &info->KeyId;
2179 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2180 items[cItem].pvStructInfo = &swapped[cSwapped];
2181 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2185 if (info->AuthorityCertIssuer.cAltEntry)
2187 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2188 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2189 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2190 items[cItem].pvStructInfo = &swapped[cSwapped];
2191 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2195 if (info->AuthorityCertSerialNumber.cbData)
2197 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2198 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2199 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2200 items[cItem].pvStructInfo = &swapped[cSwapped];
2201 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2205 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2206 pEncodePara, pbEncoded, pcbEncoded);
2210 SetLastError(STATUS_ACCESS_VIOLATION);
2217 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2218 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2219 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2225 const CERT_BASIC_CONSTRAINTS_INFO *info =
2226 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2227 struct AsnEncodeSequenceItem items[3] = {
2228 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2233 if (info->fPathLenConstraint)
2235 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2236 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2239 if (info->cSubtreesConstraint)
2241 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2242 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2245 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2246 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2250 SetLastError(STATUS_ACCESS_VIOLATION);
2257 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2258 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2259 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2265 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2266 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2267 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2272 items[cItem].pvStructInfo = &info->fCA;
2273 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2276 if (info->fPathLenConstraint)
2278 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2279 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2282 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2283 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2287 SetLastError(STATUS_ACCESS_VIOLATION);
2294 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2295 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2296 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2302 const BLOBHEADER *hdr =
2303 (const BLOBHEADER *)pvStructInfo;
2305 if (hdr->bType != PUBLICKEYBLOB)
2307 SetLastError(E_INVALIDARG);
2312 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2313 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2314 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2315 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2316 struct AsnEncodeSequenceItem items[] = {
2317 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2318 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2321 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2322 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2328 SetLastError(STATUS_ACCESS_VIOLATION);
2335 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2336 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2337 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2343 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2344 DWORD bytesNeeded, lenBytes;
2346 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2347 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2349 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2350 bytesNeeded = 1 + lenBytes + blob->cbData;
2353 *pcbEncoded = bytesNeeded;
2358 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2359 pcbEncoded, bytesNeeded)))
2361 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2362 pbEncoded = *(BYTE **)pbEncoded;
2363 *pbEncoded++ = ASN_OCTETSTRING;
2364 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2365 pbEncoded += lenBytes;
2367 memcpy(pbEncoded, blob->pbData, blob->cbData);
2373 SetLastError(STATUS_ACCESS_VIOLATION);
2377 TRACE("returning %d (%08x)\n", ret, GetLastError());
2381 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2382 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2383 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2389 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2390 DWORD bytesNeeded, lenBytes, dataBytes;
2393 /* yep, MS allows cUnusedBits to be >= 8 */
2394 if (!blob->cUnusedBits)
2396 dataBytes = blob->cbData;
2399 else if (blob->cbData * 8 > blob->cUnusedBits)
2401 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2402 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2410 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2411 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2414 *pcbEncoded = bytesNeeded;
2419 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2420 pcbEncoded, bytesNeeded)))
2422 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2423 pbEncoded = *(BYTE **)pbEncoded;
2424 *pbEncoded++ = ASN_BITSTRING;
2425 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2426 pbEncoded += lenBytes;
2427 *pbEncoded++ = unusedBits;
2430 BYTE mask = 0xff << unusedBits;
2434 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2435 pbEncoded += dataBytes - 1;
2437 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2444 SetLastError(STATUS_ACCESS_VIOLATION);
2451 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2452 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2453 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2459 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2460 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2465 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2470 for (i = 0; i < newBlob.cbData; i++)
2471 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2477 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2478 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2479 CryptMemFree(newBlob.pbData);
2483 SetLastError(STATUS_ACCESS_VIOLATION);
2490 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2491 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2492 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2494 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2496 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2497 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2500 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2501 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2502 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2508 DWORD significantBytes, lenBytes;
2509 BYTE padByte = 0, bytesNeeded;
2511 const CRYPT_INTEGER_BLOB *blob =
2512 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2514 significantBytes = blob->cbData;
2515 if (significantBytes)
2517 if (blob->pbData[significantBytes - 1] & 0x80)
2519 /* negative, lop off leading (little-endian) 0xffs */
2520 for (; significantBytes > 0 &&
2521 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2523 if (blob->pbData[significantBytes - 1] < 0x80)
2531 /* positive, lop off leading (little-endian) zeroes */
2532 for (; significantBytes > 0 &&
2533 !blob->pbData[significantBytes - 1]; significantBytes--)
2535 if (significantBytes == 0)
2536 significantBytes = 1;
2537 if (blob->pbData[significantBytes - 1] > 0x7f)
2545 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2547 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2548 bytesNeeded = 1 + lenBytes + significantBytes;
2553 *pcbEncoded = bytesNeeded;
2558 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2559 pcbEncoded, bytesNeeded)))
2561 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2562 pbEncoded = *(BYTE **)pbEncoded;
2563 *pbEncoded++ = ASN_INTEGER;
2566 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2567 pbEncoded += lenBytes;
2568 *pbEncoded++ = padByte;
2572 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2573 pbEncoded += lenBytes;
2575 for (; significantBytes > 0; significantBytes--)
2576 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2582 SetLastError(STATUS_ACCESS_VIOLATION);
2589 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2590 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2591 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2597 DWORD significantBytes, lenBytes;
2600 const CRYPT_INTEGER_BLOB *blob =
2601 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2603 significantBytes = blob->cbData;
2604 if (significantBytes)
2606 /* positive, lop off leading (little-endian) zeroes */
2607 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2610 if (significantBytes == 0)
2611 significantBytes = 1;
2612 if (blob->pbData[significantBytes - 1] > 0x7f)
2616 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2618 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2619 bytesNeeded = 1 + lenBytes + significantBytes;
2624 *pcbEncoded = bytesNeeded;
2629 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2630 pcbEncoded, bytesNeeded)))
2632 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2633 pbEncoded = *(BYTE **)pbEncoded;
2634 *pbEncoded++ = ASN_INTEGER;
2637 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2638 pbEncoded += lenBytes;
2643 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2644 pbEncoded += lenBytes;
2646 for (; significantBytes > 0; significantBytes--)
2647 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2653 SetLastError(STATUS_ACCESS_VIOLATION);
2660 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2661 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2662 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2664 CRYPT_INTEGER_BLOB blob;
2667 /* Encode as an unsigned integer, then change the tag to enumerated */
2668 blob.cbData = sizeof(DWORD);
2669 blob.pbData = (BYTE *)pvStructInfo;
2670 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2671 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2672 if (ret && pbEncoded)
2674 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2675 pbEncoded = *(BYTE **)pbEncoded;
2676 pbEncoded[0] = ASN_ENUMERATED;
2681 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2682 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2683 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2690 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2691 * temporary buffer because the output buffer is not NULL-terminated.
2694 static const DWORD bytesNeeded = sizeof(buf) - 1;
2698 *pcbEncoded = bytesNeeded;
2703 /* Sanity check the year, this is a two-digit year format */
2704 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2706 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2708 SetLastError(CRYPT_E_BAD_ENCODE);
2713 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2714 pbEncoded, pcbEncoded, bytesNeeded)))
2716 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2717 pbEncoded = *(BYTE **)pbEncoded;
2718 buf[0] = ASN_UTCTIME;
2719 buf[1] = bytesNeeded - 2;
2720 snprintf(buf + 2, sizeof(buf) - 2,
2721 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2722 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2723 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2724 sysTime.wMinute, sysTime.wSecond);
2725 memcpy(pbEncoded, buf, bytesNeeded);
2732 SetLastError(STATUS_ACCESS_VIOLATION);
2739 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2740 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2741 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2748 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2749 * temporary buffer because the output buffer is not NULL-terminated.
2752 static const DWORD bytesNeeded = sizeof(buf) - 1;
2756 *pcbEncoded = bytesNeeded;
2761 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2764 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2765 pcbEncoded, bytesNeeded);
2768 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2769 pbEncoded = *(BYTE **)pbEncoded;
2770 buf[0] = ASN_GENERALTIME;
2771 buf[1] = bytesNeeded - 2;
2772 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2773 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2774 sysTime.wMinute, sysTime.wSecond);
2775 memcpy(pbEncoded, buf, bytesNeeded);
2781 SetLastError(STATUS_ACCESS_VIOLATION);
2788 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2789 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2790 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2798 /* Check the year, if it's in the UTCTime range call that encode func */
2799 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2801 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2802 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2803 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2805 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2806 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2811 SetLastError(STATUS_ACCESS_VIOLATION);
2818 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2819 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2820 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2826 DWORD bytesNeeded, dataLen, lenBytes, i;
2827 const CRYPT_SEQUENCE_OF_ANY *seq =
2828 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2830 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2831 dataLen += seq->rgValue[i].cbData;
2832 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2833 bytesNeeded = 1 + lenBytes + dataLen;
2836 *pcbEncoded = bytesNeeded;
2841 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2842 pcbEncoded, bytesNeeded)))
2844 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2845 pbEncoded = *(BYTE **)pbEncoded;
2846 *pbEncoded++ = ASN_SEQUENCEOF;
2847 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2848 pbEncoded += lenBytes;
2849 for (i = 0; i < seq->cValue; i++)
2851 memcpy(pbEncoded, seq->rgValue[i].pbData,
2852 seq->rgValue[i].cbData);
2853 pbEncoded += seq->rgValue[i].cbData;
2860 SetLastError(STATUS_ACCESS_VIOLATION);
2867 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2868 BYTE *pbEncoded, DWORD *pcbEncoded)
2871 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2872 struct AsnConstructedItem constructed = { 0 };
2873 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2874 DWORD cItem = 0, cSwapped = 0;
2876 switch (distPoint->DistPointName.dwDistPointNameChoice)
2878 case CRL_DIST_POINT_NO_NAME:
2881 case CRL_DIST_POINT_FULL_NAME:
2882 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2883 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2884 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2885 constructed.tag = 0;
2886 constructed.pvStructInfo = &swapped[cSwapped];
2887 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2888 items[cItem].pvStructInfo = &constructed;
2889 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2893 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2894 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2900 if (ret && distPoint->ReasonFlags.cbData)
2902 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2903 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2904 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2905 items[cItem].pvStructInfo = &swapped[cSwapped];
2906 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2910 if (ret && distPoint->CRLIssuer.cAltEntry)
2912 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2913 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2914 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2915 items[cItem].pvStructInfo = &swapped[cSwapped];
2916 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2921 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2922 pbEncoded, pcbEncoded);
2926 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2927 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2928 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2934 const CRL_DIST_POINTS_INFO *info =
2935 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2937 if (!info->cDistPoint)
2939 SetLastError(E_INVALIDARG);
2944 DWORD bytesNeeded, dataLen, lenBytes, i;
2947 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2951 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2955 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2957 /* Have to propagate index of failing character */
2963 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2964 bytesNeeded = 1 + lenBytes + dataLen;
2967 *pcbEncoded = bytesNeeded;
2972 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2973 pbEncoded, pcbEncoded, bytesNeeded)))
2975 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2976 pbEncoded = *(BYTE **)pbEncoded;
2977 *pbEncoded++ = ASN_SEQUENCEOF;
2978 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2979 pbEncoded += lenBytes;
2980 for (i = 0; ret && i < info->cDistPoint; i++)
2982 DWORD len = dataLen;
2984 ret = CRYPT_AsnEncodeDistPoint(
2985 &info->rgDistPoint[i], pbEncoded, &len);
2999 SetLastError(STATUS_ACCESS_VIOLATION);
3006 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3007 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3008 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3014 const CERT_ENHKEY_USAGE *usage =
3015 (const CERT_ENHKEY_USAGE *)pvStructInfo;
3016 DWORD bytesNeeded = 0, lenBytes, size, i;
3019 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3021 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3022 usage->rgpszUsageIdentifier[i],
3023 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3025 bytesNeeded += size;
3027 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3028 bytesNeeded += 1 + lenBytes;
3032 *pcbEncoded = bytesNeeded;
3035 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3036 pbEncoded, pcbEncoded, bytesNeeded)))
3038 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3039 pbEncoded = *(BYTE **)pbEncoded;
3040 *pbEncoded++ = ASN_SEQUENCEOF;
3041 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
3043 pbEncoded += lenBytes;
3044 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3047 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3048 usage->rgpszUsageIdentifier[i],
3049 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
3054 bytesNeeded -= size;
3063 SetLastError(STATUS_ACCESS_VIOLATION);
3070 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3071 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3072 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3078 const CRL_ISSUING_DIST_POINT *point =
3079 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3080 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3081 struct AsnConstructedItem constructed = { 0 };
3082 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3083 DWORD cItem = 0, cSwapped = 0;
3086 switch (point->DistPointName.dwDistPointNameChoice)
3088 case CRL_DIST_POINT_NO_NAME:
3091 case CRL_DIST_POINT_FULL_NAME:
3092 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3093 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3094 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3095 constructed.tag = 0;
3096 constructed.pvStructInfo = &swapped[cSwapped];
3097 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3098 items[cItem].pvStructInfo = &constructed;
3099 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3104 SetLastError(E_INVALIDARG);
3107 if (ret && point->fOnlyContainsUserCerts)
3109 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3110 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3111 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3112 items[cItem].pvStructInfo = &swapped[cSwapped];
3113 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3117 if (ret && point->fOnlyContainsCACerts)
3119 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3120 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3121 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3122 items[cItem].pvStructInfo = &swapped[cSwapped];
3123 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3127 if (ret && point->OnlySomeReasonFlags.cbData)
3129 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3130 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3131 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3132 items[cItem].pvStructInfo = &swapped[cSwapped];
3133 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3137 if (ret && point->fIndirectCRL)
3139 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3140 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3141 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3142 items[cItem].pvStructInfo = &swapped[cSwapped];
3143 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3148 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3149 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3153 SetLastError(STATUS_ACCESS_VIOLATION);
3160 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3161 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3162 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3166 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3167 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3168 struct AsnEncodeSequenceItem items[] = {
3169 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3170 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3173 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3174 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3179 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3180 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3181 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3185 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3187 SetLastError(E_INVALIDARG);
3193 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3195 if (!info->Issuer.cbData)
3196 SetLastError(E_INVALIDARG);
3199 struct AsnEncodeSequenceItem items[7] = {
3200 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3201 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3202 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
3204 { &info->HashEncryptionAlgorithm,
3205 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
3209 if (info->AuthAttrs.cAttr)
3211 items[cItem].pvStructInfo = &info->AuthAttrs;
3212 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3215 if (info->UnauthAttrs.cAttr)
3217 items[cItem].pvStructInfo = &info->UnauthAttrs;
3218 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3221 items[cItem].pvStructInfo = &info->EncryptedHash;
3222 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3224 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3225 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3230 SetLastError(STATUS_ACCESS_VIOLATION);
3236 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3237 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3238 void *pvEncoded, DWORD *pcbEncoded)
3240 static HCRYPTOIDFUNCSET set = NULL;
3242 CryptEncodeObjectExFunc encodeFunc = NULL;
3243 HCRYPTOIDFUNCADDR hFunc = NULL;
3245 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3246 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3247 pvEncoded, pcbEncoded);
3249 if (!pvEncoded && !pcbEncoded)
3251 SetLastError(ERROR_INVALID_PARAMETER);
3254 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3255 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3257 SetLastError(ERROR_FILE_NOT_FOUND);
3261 SetLastError(NOERROR);
3262 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3263 *(BYTE **)pvEncoded = NULL;
3264 if (!HIWORD(lpszStructType))
3266 switch (LOWORD(lpszStructType))
3268 case (WORD)X509_CERT:
3269 encodeFunc = CRYPT_AsnEncodeCert;
3271 case (WORD)X509_CERT_TO_BE_SIGNED:
3272 encodeFunc = CRYPT_AsnEncodeCertInfo;
3274 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3275 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3277 case (WORD)X509_EXTENSIONS:
3278 encodeFunc = CRYPT_AsnEncodeExtensions;
3280 case (WORD)X509_NAME_VALUE:
3281 encodeFunc = CRYPT_AsnEncodeNameValue;
3283 case (WORD)X509_NAME:
3284 encodeFunc = CRYPT_AsnEncodeName;
3286 case (WORD)X509_PUBLIC_KEY_INFO:
3287 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3289 case (WORD)X509_AUTHORITY_KEY_ID:
3290 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3292 case (WORD)X509_ALTERNATE_NAME:
3293 encodeFunc = CRYPT_AsnEncodeAltName;
3295 case (WORD)X509_BASIC_CONSTRAINTS:
3296 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3298 case (WORD)X509_BASIC_CONSTRAINTS2:
3299 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3301 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3302 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3304 case (WORD)X509_UNICODE_NAME:
3305 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3307 case (WORD)PKCS_CONTENT_INFO:
3308 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3310 case (WORD)PKCS_ATTRIBUTE:
3311 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3313 case (WORD)X509_UNICODE_NAME_VALUE:
3314 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3316 case (WORD)X509_OCTET_STRING:
3317 encodeFunc = CRYPT_AsnEncodeOctets;
3319 case (WORD)X509_BITS:
3320 case (WORD)X509_KEY_USAGE:
3321 encodeFunc = CRYPT_AsnEncodeBits;
3323 case (WORD)X509_INTEGER:
3324 encodeFunc = CRYPT_AsnEncodeInt;
3326 case (WORD)X509_MULTI_BYTE_INTEGER:
3327 encodeFunc = CRYPT_AsnEncodeInteger;
3329 case (WORD)X509_MULTI_BYTE_UINT:
3330 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3332 case (WORD)X509_ENUMERATED:
3333 encodeFunc = CRYPT_AsnEncodeEnumerated;
3335 case (WORD)X509_CHOICE_OF_TIME:
3336 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3338 case (WORD)X509_AUTHORITY_KEY_ID2:
3339 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3341 case (WORD)X509_SEQUENCE_OF_ANY:
3342 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3344 case (WORD)PKCS_UTC_TIME:
3345 encodeFunc = CRYPT_AsnEncodeUtcTime;
3347 case (WORD)X509_CRL_DIST_POINTS:
3348 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3350 case (WORD)X509_ENHANCED_KEY_USAGE:
3351 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3353 case (WORD)PKCS_ATTRIBUTES:
3354 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3356 case (WORD)X509_ISSUING_DIST_POINT:
3357 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3359 case (WORD)PKCS7_SIGNER_INFO:
3360 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3363 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3366 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3367 encodeFunc = CRYPT_AsnEncodeExtensions;
3368 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3369 encodeFunc = CRYPT_AsnEncodeUtcTime;
3370 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3371 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3372 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3373 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3374 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3375 encodeFunc = CRYPT_AsnEncodeEnumerated;
3376 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3377 encodeFunc = CRYPT_AsnEncodeBits;
3378 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3379 encodeFunc = CRYPT_AsnEncodeOctets;
3380 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3381 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3382 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3383 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3384 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3385 encodeFunc = CRYPT_AsnEncodeAltName;
3386 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3387 encodeFunc = CRYPT_AsnEncodeAltName;
3388 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3389 encodeFunc = CRYPT_AsnEncodeAltName;
3390 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3391 encodeFunc = CRYPT_AsnEncodeAltName;
3392 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3393 encodeFunc = CRYPT_AsnEncodeAltName;
3394 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3395 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3396 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3397 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3398 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3399 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3401 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3402 debugstr_a(lpszStructType));
3406 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3407 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3408 (void **)&encodeFunc, &hFunc);
3411 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3412 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3414 SetLastError(ERROR_FILE_NOT_FOUND);
3416 CryptFreeOIDFunctionAddress(hFunc, 0);
3420 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3421 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3423 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3424 NULL, 0, NULL, pInfo, pcbInfo);
3427 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3428 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3429 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3433 static CHAR oid[] = szOID_RSA_RSA;
3435 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3436 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3439 if (!pszPublicKeyObjId)
3440 pszPublicKeyObjId = oid;
3441 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3445 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3448 LPBYTE pubKey = CryptMemAlloc(keySize);
3452 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3456 DWORD encodedLen = 0;
3458 ret = CryptEncodeObject(dwCertEncodingType,
3459 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3462 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3463 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3466 *pcbInfo = sizeNeeded;
3467 else if (*pcbInfo < sizeNeeded)
3469 SetLastError(ERROR_MORE_DATA);
3470 *pcbInfo = sizeNeeded;
3475 pInfo->Algorithm.pszObjId = (char *)pInfo +
3476 sizeof(CERT_PUBLIC_KEY_INFO);
3477 lstrcpyA(pInfo->Algorithm.pszObjId,
3479 pInfo->Algorithm.Parameters.cbData = 0;
3480 pInfo->Algorithm.Parameters.pbData = NULL;
3481 pInfo->PublicKey.pbData =
3482 (BYTE *)pInfo->Algorithm.pszObjId
3483 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3484 pInfo->PublicKey.cbData = encodedLen;
3485 pInfo->PublicKey.cUnusedBits = 0;
3486 ret = CryptEncodeObject(dwCertEncodingType,
3487 RSA_CSP_PUBLICKEYBLOB, pubKey,
3488 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3492 CryptMemFree(pubKey);
3497 CryptDestroyKey(key);
3502 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3503 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3504 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3506 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3507 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3508 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3510 static HCRYPTOIDFUNCSET set = NULL;
3512 ExportPublicKeyInfoExFunc exportFunc = NULL;
3513 HCRYPTOIDFUNCADDR hFunc = NULL;
3515 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3516 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3521 SetLastError(ERROR_INVALID_PARAMETER);
3525 if (pszPublicKeyObjId)
3528 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3530 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3531 0, (void **)&exportFunc, &hFunc);
3534 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3535 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3536 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3538 CryptFreeOIDFunctionAddress(hFunc, 0);
3542 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3543 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3545 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3549 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3550 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3551 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3554 DWORD pubKeySize = 0;
3556 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3557 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3559 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3560 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3563 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3567 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3568 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3571 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3573 CryptMemFree(pubKey);
3581 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3582 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3583 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3585 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3586 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3587 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3589 static HCRYPTOIDFUNCSET set = NULL;
3591 ImportPublicKeyInfoExFunc importFunc = NULL;
3592 HCRYPTOIDFUNCADDR hFunc = NULL;
3594 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3595 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3598 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3599 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3600 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3602 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3603 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3606 CryptFreeOIDFunctionAddress(hFunc, 0);