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
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(crypt);
54 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
57 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
59 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
60 * The dwCertEncodingType and lpszStructType are ignored by the built-in
61 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
62 * since it must call functions in external DLLs that follow these signatures.
64 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
65 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
66 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
67 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
68 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
69 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
70 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
71 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
72 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
73 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
74 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
75 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
76 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
77 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
78 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
79 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
80 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
81 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
82 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
83 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
84 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
85 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
87 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
88 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
90 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
91 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
92 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
93 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
94 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
96 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
97 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
99 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
101 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
102 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
104 static HCRYPTOIDFUNCSET set = NULL;
106 HCRYPTOIDFUNCADDR hFunc;
107 CryptEncodeObjectFunc pCryptEncodeObject;
109 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
110 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
113 if (!pbEncoded && !pcbEncoded)
115 SetLastError(ERROR_INVALID_PARAMETER);
119 /* Try registered DLL first.. */
121 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
122 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
123 (void **)&pCryptEncodeObject, &hFunc);
124 if (pCryptEncodeObject)
126 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
127 pvStructInfo, pbEncoded, pcbEncoded);
128 CryptFreeOIDFunctionAddress(hFunc, 0);
132 /* If not, use CryptEncodeObjectEx */
133 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
134 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
139 /* Helper function to check *pcbEncoded, set it to the required size, and
140 * optionally to allocate memory. Assumes pbEncoded is not NULL.
141 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
142 * pointer to the newly allocated memory.
144 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
145 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
150 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
152 if (pEncodePara && pEncodePara->pfnAlloc)
153 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
155 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
156 if (!*(BYTE **)pbEncoded)
159 *pcbEncoded = bytesNeeded;
161 else if (bytesNeeded > *pcbEncoded)
163 *pcbEncoded = bytesNeeded;
164 SetLastError(ERROR_MORE_DATA);
168 *pcbEncoded = bytesNeeded;
172 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
174 DWORD bytesNeeded, significantBytes = 0;
182 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
183 temp <<= 8, significantBytes--)
185 bytesNeeded = significantBytes + 1;
189 *pcbEncoded = bytesNeeded;
192 if (*pcbEncoded < bytesNeeded)
194 SetLastError(ERROR_MORE_DATA);
198 *pbEncoded = (BYTE)len;
203 *pbEncoded++ = significantBytes | 0x80;
204 for (i = 0; i < significantBytes; i++)
206 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
210 *pcbEncoded = bytesNeeded;
214 struct AsnEncodeSequenceItem
216 const void *pvStructInfo;
217 CryptEncodeObjectExFunc encodeFunc;
218 DWORD size; /* used during encoding, not for your use */
221 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
222 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
223 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
226 DWORD i, dataLen = 0;
228 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
229 pbEncoded, *pcbEncoded);
230 for (i = 0, ret = TRUE; ret && i < cItem; i++)
232 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
233 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
234 NULL, &items[i].size);
235 /* Some functions propagate their errors through the size */
237 *pcbEncoded = items[i].size;
238 dataLen += items[i].size;
242 DWORD lenBytes, bytesNeeded;
244 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
245 bytesNeeded = 1 + lenBytes + dataLen;
247 *pcbEncoded = bytesNeeded;
250 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
251 pcbEncoded, bytesNeeded)))
253 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
254 pbEncoded = *(BYTE **)pbEncoded;
255 *pbEncoded++ = ASN_SEQUENCE;
256 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
257 pbEncoded += lenBytes;
258 for (i = 0; ret && i < cItem; i++)
260 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
261 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
262 NULL, pbEncoded, &items[i].size);
263 /* Some functions propagate their errors through the size */
265 *pcbEncoded = items[i].size;
266 pbEncoded += items[i].size;
271 TRACE("returning %d (%08x)\n", ret, GetLastError());
275 struct AsnConstructedItem
278 const void *pvStructInfo;
279 CryptEncodeObjectExFunc encodeFunc;
282 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
283 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
284 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
287 const struct AsnConstructedItem *item =
288 (const struct AsnConstructedItem *)pvStructInfo;
291 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
292 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
294 DWORD dataLen, bytesNeeded;
296 CRYPT_EncodeLen(len, NULL, &dataLen);
297 bytesNeeded = 1 + dataLen + len;
299 *pcbEncoded = bytesNeeded;
300 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
301 pbEncoded, pcbEncoded, bytesNeeded)))
303 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
304 pbEncoded = *(BYTE **)pbEncoded;
305 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
306 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
307 pbEncoded += dataLen;
308 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
309 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
313 /* Some functions propagate their errors through the size */
320 /* Some functions propagate their errors through the size */
326 struct AsnEncodeTagSwappedItem
329 const void *pvStructInfo;
330 CryptEncodeObjectExFunc encodeFunc;
333 /* Sort of a wacky hack, it encodes something using the struct
334 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
335 * given in the struct AsnEncodeTagSwappedItem.
337 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
338 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
339 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
342 const struct AsnEncodeTagSwappedItem *item =
343 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
345 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
346 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
347 if (ret && pbEncoded)
348 *pbEncoded = item->tag;
352 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
353 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
354 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
356 const DWORD *ver = (const DWORD *)pvStructInfo;
359 /* CERT_V1 is not encoded */
367 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
369 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
370 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
375 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
376 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
377 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
379 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
384 *pcbEncoded = blob->cbData;
389 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
390 pcbEncoded, blob->cbData)))
392 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
393 pbEncoded = *(BYTE **)pbEncoded;
395 memcpy(pbEncoded, blob->pbData, blob->cbData);
396 *pcbEncoded = blob->cbData;
403 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
404 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
405 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
408 /* This has two filetimes in a row, a NotBefore and a NotAfter */
409 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
410 struct AsnEncodeSequenceItem items[] = {
411 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
412 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
415 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
416 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
421 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
422 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
423 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
426 const CRYPT_ALGORITHM_IDENTIFIER *algo =
427 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
429 struct AsnEncodeSequenceItem items[] = {
430 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
431 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
434 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
435 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
440 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
441 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
442 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
448 const CERT_PUBLIC_KEY_INFO *info =
449 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
450 struct AsnEncodeSequenceItem items[] = {
451 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
452 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
455 TRACE("Encoding public key with OID %s\n",
456 debugstr_a(info->Algorithm.pszObjId));
457 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
458 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
463 SetLastError(STATUS_ACCESS_VIOLATION);
470 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
471 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
472 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
478 const CERT_SIGNED_CONTENT_INFO *info =
479 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
480 struct AsnEncodeSequenceItem items[] = {
481 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
482 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
483 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
486 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
487 items[2].encodeFunc = CRYPT_AsnEncodeBits;
488 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
489 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
494 SetLastError(STATUS_ACCESS_VIOLATION);
501 /* Like in Windows, this blithely ignores the validity of the passed-in
502 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
503 * decode properly, see CRYPT_AsnDecodeCertInfo.
505 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
506 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
507 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
513 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
514 struct AsnEncodeSequenceItem items[10] = {
515 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
516 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
517 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
518 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
519 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
520 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
521 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
524 struct AsnConstructedItem constructed[3] = { { 0 } };
525 DWORD cItem = 7, cConstructed = 0;
527 if (info->IssuerUniqueId.cbData)
529 constructed[cConstructed].tag = 1;
530 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
531 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
532 items[cItem].pvStructInfo = &constructed[cConstructed];
533 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
537 if (info->SubjectUniqueId.cbData)
539 constructed[cConstructed].tag = 2;
540 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
541 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
542 items[cItem].pvStructInfo = &constructed[cConstructed];
543 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
547 if (info->cExtension)
549 constructed[cConstructed].tag = 3;
550 constructed[cConstructed].pvStructInfo = &info->cExtension;
551 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
552 items[cItem].pvStructInfo = &constructed[cConstructed];
553 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
558 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
559 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
563 SetLastError(STATUS_ACCESS_VIOLATION);
570 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
571 BYTE *pbEncoded, DWORD *pcbEncoded)
573 struct AsnEncodeSequenceItem items[3] = {
574 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
575 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
581 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
583 if (entry->cExtension)
585 items[cItem].pvStructInfo = &entry->cExtension;
586 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
590 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
591 pbEncoded, pcbEncoded);
593 TRACE("returning %d (%08x)\n", ret, GetLastError());
597 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
598 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
599 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
601 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
602 DWORD bytesNeeded, dataLen, lenBytes, i;
603 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
604 ((const BYTE *)pvStructInfo + sizeof(DWORD));
607 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
611 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
615 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
616 bytesNeeded = 1 + lenBytes + dataLen;
618 *pcbEncoded = bytesNeeded;
621 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
622 pcbEncoded, bytesNeeded)))
624 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
625 pbEncoded = *(BYTE **)pbEncoded;
626 *pbEncoded++ = ASN_SEQUENCEOF;
627 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
628 pbEncoded += lenBytes;
629 for (i = 0; i < cCRLEntry; i++)
631 DWORD size = dataLen;
633 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
642 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
643 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
644 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
646 const DWORD *ver = (const DWORD *)pvStructInfo;
649 /* CRL_V1 is not encoded */
656 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
657 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
661 /* Like in Windows, this blithely ignores the validity of the passed-in
662 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
663 * decode properly, see CRYPT_AsnDecodeCRLInfo.
665 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
666 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
667 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
673 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
674 struct AsnEncodeSequenceItem items[7] = {
675 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
676 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
677 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
678 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
681 struct AsnConstructedItem constructed[1] = { { 0 } };
682 DWORD cItem = 4, cConstructed = 0;
684 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
686 items[cItem].pvStructInfo = &info->NextUpdate;
687 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
692 items[cItem].pvStructInfo = &info->cCRLEntry;
693 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
696 if (info->cExtension)
698 constructed[cConstructed].tag = 0;
699 constructed[cConstructed].pvStructInfo = &info->cExtension;
700 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
701 items[cItem].pvStructInfo = &constructed[cConstructed];
702 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
707 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
708 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
712 SetLastError(STATUS_ACCESS_VIOLATION);
719 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
723 struct AsnEncodeSequenceItem items[3] = {
724 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
730 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
734 items[cItem].pvStructInfo = &ext->fCritical;
735 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
738 items[cItem].pvStructInfo = &ext->Value;
739 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
742 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
743 pbEncoded, pcbEncoded);
744 TRACE("returning %d (%08x)\n", ret, GetLastError());
748 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
749 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
750 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
756 DWORD bytesNeeded, dataLen, lenBytes, i;
757 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
760 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
764 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
768 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
769 bytesNeeded = 1 + lenBytes + dataLen;
771 *pcbEncoded = bytesNeeded;
774 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
775 pcbEncoded, bytesNeeded)))
777 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
778 pbEncoded = *(BYTE **)pbEncoded;
779 *pbEncoded++ = ASN_SEQUENCEOF;
780 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
781 pbEncoded += lenBytes;
782 for (i = 0; i < exts->cExtension; i++)
784 DWORD size = dataLen;
786 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
796 SetLastError(STATUS_ACCESS_VIOLATION);
803 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
804 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
805 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
807 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
808 DWORD bytesNeeded = 0, lenBytes;
813 TRACE("%s\n", debugstr_a(pszObjId));
820 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
822 SetLastError(CRYPT_E_ASN1_ERROR);
826 firstByte = val1 * 40 + val2;
827 ptr = pszObjId + firstPos;
832 /* note I assume each component is at most 32-bits long in base 2 */
833 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
835 if (val1 >= 0x10000000)
837 else if (val1 >= 0x200000)
839 else if (val1 >= 0x4000)
841 else if (val1 >= 0x80)
851 SetLastError(CRYPT_E_ASN1_ERROR);
855 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
859 bytesNeeded += 1 + lenBytes;
862 if (*pcbEncoded < bytesNeeded)
864 SetLastError(ERROR_MORE_DATA);
869 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
870 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
871 pbEncoded += lenBytes;
877 *pbEncoded++ = firstByte;
878 ptr = pszObjId + firstPos;
881 sscanf(ptr, "%d%n", &val, &pos);
883 unsigned char outBytes[5];
886 if (val >= 0x10000000)
888 else if (val >= 0x200000)
890 else if (val >= 0x4000)
892 else if (val >= 0x80)
896 for (i = numBytes; i > 0; i--)
898 outBytes[i - 1] = val & 0x7f;
901 for (i = 0; i < numBytes - 1; i++)
902 *pbEncoded++ = outBytes[i] | 0x80;
903 *pbEncoded++ = outBytes[i];
912 *pcbEncoded = bytesNeeded;
916 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
917 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
921 LPCSTR str = (LPCSTR)value->Value.pbData;
922 DWORD bytesNeeded, lenBytes, encodedLen;
924 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
925 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
926 bytesNeeded = 1 + lenBytes + encodedLen;
928 *pcbEncoded = bytesNeeded;
931 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
932 pbEncoded, pcbEncoded, bytesNeeded)))
934 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
935 pbEncoded = *(BYTE **)pbEncoded;
937 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
938 pbEncoded += lenBytes;
939 memcpy(pbEncoded, str, encodedLen);
945 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
946 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
950 LPCWSTR str = (LPCWSTR)value->Value.pbData;
951 DWORD bytesNeeded, lenBytes, strLen;
953 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
955 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
956 bytesNeeded = 1 + lenBytes + strLen * 2;
958 *pcbEncoded = bytesNeeded;
961 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
962 pbEncoded, pcbEncoded, bytesNeeded)))
966 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
967 pbEncoded = *(BYTE **)pbEncoded;
968 *pbEncoded++ = ASN_BMPSTRING;
969 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
970 pbEncoded += lenBytes;
971 for (i = 0; i < strLen; i++)
973 *pbEncoded++ = (str[i] & 0xff00) >> 8;
974 *pbEncoded++ = str[i] & 0x00ff;
981 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
982 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
986 LPCWSTR str = (LPCWSTR)value->Value.pbData;
987 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
989 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
991 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
993 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
994 bytesNeeded = 1 + lenBytes + encodedLen;
996 *pcbEncoded = bytesNeeded;
999 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1000 pbEncoded, pcbEncoded, bytesNeeded)))
1002 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1003 pbEncoded = *(BYTE **)pbEncoded;
1004 *pbEncoded++ = ASN_UTF8STRING;
1005 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1006 pbEncoded += lenBytes;
1007 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1008 bytesNeeded - lenBytes - 1, NULL, NULL);
1014 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1015 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1016 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1022 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1024 switch (value->dwValueType)
1026 case CERT_RDN_ANY_TYPE:
1027 /* explicitly disallowed */
1028 SetLastError(E_INVALIDARG);
1031 case CERT_RDN_ENCODED_BLOB:
1032 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1033 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1035 case CERT_RDN_OCTET_STRING:
1036 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1037 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1039 case CERT_RDN_NUMERIC_STRING:
1040 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1041 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1043 case CERT_RDN_PRINTABLE_STRING:
1044 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1045 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1047 case CERT_RDN_TELETEX_STRING:
1048 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1049 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1051 case CERT_RDN_VIDEOTEX_STRING:
1052 ret = CRYPT_AsnEncodeStringCoerce(value,
1053 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1055 case CERT_RDN_IA5_STRING:
1056 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1057 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1059 case CERT_RDN_GRAPHIC_STRING:
1060 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1061 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1063 case CERT_RDN_VISIBLE_STRING:
1064 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1065 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1067 case CERT_RDN_GENERAL_STRING:
1068 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1069 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1071 case CERT_RDN_UNIVERSAL_STRING:
1072 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1073 SetLastError(CRYPT_E_ASN1_CHOICE);
1076 case CERT_RDN_BMP_STRING:
1077 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1078 pbEncoded, pcbEncoded);
1080 case CERT_RDN_UTF8_STRING:
1081 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1082 pbEncoded, pcbEncoded);
1085 SetLastError(CRYPT_E_ASN1_CHOICE);
1091 SetLastError(STATUS_ACCESS_VIOLATION);
1098 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1099 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1100 BYTE *pbEncoded, DWORD *pcbEncoded)
1102 DWORD bytesNeeded = 0, lenBytes, size;
1105 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1106 0, NULL, NULL, &size);
1109 bytesNeeded += size;
1110 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1111 * with dwValueType, so "cast" it to get its encoded size
1113 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1114 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1117 bytesNeeded += size;
1118 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1119 bytesNeeded += 1 + lenBytes;
1122 if (*pcbEncoded < bytesNeeded)
1124 SetLastError(ERROR_MORE_DATA);
1129 *pbEncoded++ = ASN_SEQUENCE;
1130 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1132 pbEncoded += lenBytes;
1133 size = bytesNeeded - 1 - lenBytes;
1134 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1135 attr->pszObjId, 0, NULL, pbEncoded, &size);
1139 size = bytesNeeded - 1 - lenBytes - size;
1140 ret = nameValueEncodeFunc(dwCertEncodingType,
1141 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1142 0, NULL, pbEncoded, &size);
1149 *pcbEncoded = bytesNeeded;
1153 /* Have to propagate index of failing character */
1160 static int BLOBComp(const void *l, const void *r)
1162 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1165 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1166 ret = a->cbData - b->cbData;
1170 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1172 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1173 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1177 CRYPT_DER_BLOB *blobs = NULL;
1181 DWORD bytesNeeded = 0, lenBytes, i;
1187 blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1191 memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1193 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1195 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1196 nameValueEncodeFunc, NULL, &blobs[i].cbData);
1198 bytesNeeded += blobs[i].cbData;
1201 /* Have to propagate index of failing character */
1202 *pcbEncoded = blobs[i].cbData;
1207 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1208 bytesNeeded += 1 + lenBytes;
1211 if (*pcbEncoded < bytesNeeded)
1213 SetLastError(ERROR_MORE_DATA);
1218 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1220 blobs[i].pbData = CryptMemAlloc(blobs[i].cbData);
1221 if (!blobs[i].pbData)
1225 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1226 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1227 blobs[i].pbData, &blobs[i].cbData);
1229 *pcbEncoded = blobs[i].cbData;
1234 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
1236 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1237 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1239 pbEncoded += lenBytes;
1240 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1242 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
1243 pbEncoded += blobs[i].cbData;
1249 *pcbEncoded = bytesNeeded;
1253 for (i = 0; i < rdn->cRDNAttr; i++)
1254 CryptMemFree(blobs[i].pbData);
1259 SetLastError(STATUS_ACCESS_VIOLATION);
1263 CryptMemFree(blobs);
1267 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1268 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1269 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1271 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1272 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1273 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1276 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1279 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1280 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1281 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1283 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1284 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1288 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1289 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1290 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1296 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1297 DWORD bytesNeeded = 0, lenBytes, size, i;
1299 TRACE("encoding name with %d RDNs\n", info->cRDN);
1301 for (i = 0; ret && i < info->cRDN; i++)
1303 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1304 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1306 bytesNeeded += size;
1310 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1311 bytesNeeded += 1 + lenBytes;
1315 *pcbEncoded = bytesNeeded;
1318 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1319 pbEncoded, pcbEncoded, bytesNeeded)))
1321 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1322 pbEncoded = *(BYTE **)pbEncoded;
1323 *pbEncoded++ = ASN_SEQUENCEOF;
1324 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1326 pbEncoded += lenBytes;
1327 for (i = 0; ret && i < info->cRDN; i++)
1330 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1331 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1336 bytesNeeded -= size;
1347 SetLastError(STATUS_ACCESS_VIOLATION);
1354 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1355 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1359 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1360 DWORD bytesNeeded, lenBytes, encodedLen;
1362 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1364 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1365 bytesNeeded = 1 + lenBytes + encodedLen;
1367 *pcbEncoded = bytesNeeded;
1370 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1371 pbEncoded, pcbEncoded, bytesNeeded)))
1375 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1376 pbEncoded = *(BYTE **)pbEncoded;
1378 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1379 pbEncoded += lenBytes;
1380 for (i = 0; i < encodedLen; i++)
1381 *pbEncoded++ = (BYTE)str[i];
1387 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1388 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1392 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1393 DWORD bytesNeeded, lenBytes, encodedLen;
1395 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1397 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1398 bytesNeeded = 1 + lenBytes + encodedLen;
1400 *pcbEncoded = bytesNeeded;
1403 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1404 pbEncoded, pcbEncoded, bytesNeeded)))
1408 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1409 pbEncoded = *(BYTE **)pbEncoded;
1410 *pbEncoded++ = ASN_NUMERICSTRING;
1411 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1412 pbEncoded += lenBytes;
1413 for (i = 0; ret && i < encodedLen; i++)
1415 if (isdigitW(str[i]))
1416 *pbEncoded++ = (BYTE)str[i];
1420 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1429 static inline int isprintableW(WCHAR wc)
1431 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1432 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1433 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1436 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1437 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1441 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1442 DWORD bytesNeeded, lenBytes, encodedLen;
1444 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1446 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1447 bytesNeeded = 1 + lenBytes + encodedLen;
1449 *pcbEncoded = bytesNeeded;
1452 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1453 pbEncoded, pcbEncoded, bytesNeeded)))
1457 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1458 pbEncoded = *(BYTE **)pbEncoded;
1459 *pbEncoded++ = ASN_PRINTABLESTRING;
1460 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1461 pbEncoded += lenBytes;
1462 for (i = 0; ret && i < encodedLen; i++)
1464 if (isprintableW(str[i]))
1465 *pbEncoded++ = (BYTE)str[i];
1469 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1478 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1479 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1483 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1484 DWORD bytesNeeded, lenBytes, encodedLen;
1486 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1488 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1489 bytesNeeded = 1 + lenBytes + encodedLen;
1491 *pcbEncoded = bytesNeeded;
1494 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1495 pbEncoded, pcbEncoded, bytesNeeded)))
1499 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1500 pbEncoded = *(BYTE **)pbEncoded;
1501 *pbEncoded++ = ASN_IA5STRING;
1502 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1503 pbEncoded += lenBytes;
1504 for (i = 0; ret && i < encodedLen; i++)
1507 *pbEncoded++ = (BYTE)str[i];
1511 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1520 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1521 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1525 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1526 DWORD bytesNeeded, lenBytes, strLen;
1528 /* FIXME: doesn't handle composite characters */
1529 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1531 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1532 bytesNeeded = 1 + lenBytes + strLen * 4;
1534 *pcbEncoded = bytesNeeded;
1537 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1538 pbEncoded, pcbEncoded, bytesNeeded)))
1542 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1543 pbEncoded = *(BYTE **)pbEncoded;
1544 *pbEncoded++ = ASN_UNIVERSALSTRING;
1545 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1546 pbEncoded += lenBytes;
1547 for (i = 0; i < strLen; i++)
1551 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1552 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1559 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1560 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1561 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1567 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1569 switch (value->dwValueType)
1571 case CERT_RDN_ANY_TYPE:
1572 case CERT_RDN_ENCODED_BLOB:
1573 case CERT_RDN_OCTET_STRING:
1574 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1576 case CERT_RDN_NUMERIC_STRING:
1577 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1578 pbEncoded, pcbEncoded);
1580 case CERT_RDN_PRINTABLE_STRING:
1581 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1582 pbEncoded, pcbEncoded);
1584 case CERT_RDN_TELETEX_STRING:
1585 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1586 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1588 case CERT_RDN_VIDEOTEX_STRING:
1589 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1590 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1592 case CERT_RDN_IA5_STRING:
1593 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1594 pbEncoded, pcbEncoded);
1596 case CERT_RDN_GRAPHIC_STRING:
1597 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1598 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1600 case CERT_RDN_VISIBLE_STRING:
1601 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1602 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1604 case CERT_RDN_GENERAL_STRING:
1605 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1606 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1608 case CERT_RDN_UNIVERSAL_STRING:
1609 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1610 pbEncoded, pcbEncoded);
1612 case CERT_RDN_BMP_STRING:
1613 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1614 pbEncoded, pcbEncoded);
1616 case CERT_RDN_UTF8_STRING:
1617 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1618 pbEncoded, pcbEncoded);
1621 SetLastError(CRYPT_E_ASN1_CHOICE);
1626 SetLastError(STATUS_ACCESS_VIOLATION);
1632 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1633 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1634 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1640 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1641 DWORD bytesNeeded = 0, lenBytes, size, i;
1643 TRACE("encoding name with %d RDNs\n", info->cRDN);
1645 for (i = 0; ret && i < info->cRDN; i++)
1647 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1648 CRYPT_AsnEncodeNameValue, NULL, &size);
1650 bytesNeeded += size;
1652 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1653 bytesNeeded += 1 + lenBytes;
1657 *pcbEncoded = bytesNeeded;
1660 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1661 pbEncoded, pcbEncoded, bytesNeeded)))
1663 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1664 pbEncoded = *(BYTE **)pbEncoded;
1665 *pbEncoded++ = ASN_SEQUENCEOF;
1666 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1668 pbEncoded += lenBytes;
1669 for (i = 0; ret && i < info->cRDN; i++)
1672 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1673 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1678 bytesNeeded -= size;
1687 SetLastError(STATUS_ACCESS_VIOLATION);
1694 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1695 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1696 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1698 BOOL val = *(const BOOL *)pvStructInfo, ret;
1707 else if (*pcbEncoded < 3)
1710 SetLastError(ERROR_MORE_DATA);
1716 *pbEncoded++ = ASN_BOOL;
1718 *pbEncoded++ = val ? 0xff : 0;
1721 TRACE("returning %d (%08x)\n", ret, GetLastError());
1725 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1726 BYTE *pbEncoded, DWORD *pcbEncoded)
1732 switch (entry->dwAltNameChoice)
1734 case CERT_ALT_NAME_RFC822_NAME:
1735 case CERT_ALT_NAME_DNS_NAME:
1736 case CERT_ALT_NAME_URL:
1737 if (entry->u.pwszURL)
1741 /* Not + 1: don't encode the NULL-terminator */
1742 dataLen = lstrlenW(entry->u.pwszURL);
1743 for (i = 0; ret && i < dataLen; i++)
1745 if (entry->u.pwszURL[i] > 0x7f)
1747 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1756 case CERT_ALT_NAME_IP_ADDRESS:
1757 dataLen = entry->u.IPAddress.cbData;
1759 case CERT_ALT_NAME_REGISTERED_ID:
1760 /* FIXME: encode OID */
1761 case CERT_ALT_NAME_OTHER_NAME:
1762 case CERT_ALT_NAME_DIRECTORY_NAME:
1763 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1766 SetLastError(E_INVALIDARG);
1771 DWORD bytesNeeded, lenBytes;
1773 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1774 bytesNeeded = 1 + dataLen + lenBytes;
1776 *pcbEncoded = bytesNeeded;
1777 else if (*pcbEncoded < bytesNeeded)
1779 SetLastError(ERROR_MORE_DATA);
1780 *pcbEncoded = bytesNeeded;
1785 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1786 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1787 pbEncoded += lenBytes;
1788 switch (entry->dwAltNameChoice)
1790 case CERT_ALT_NAME_RFC822_NAME:
1791 case CERT_ALT_NAME_DNS_NAME:
1792 case CERT_ALT_NAME_URL:
1796 for (i = 0; i < dataLen; i++)
1797 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1800 case CERT_ALT_NAME_IP_ADDRESS:
1801 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1805 *pcbEncoded = bytesNeeded;
1808 TRACE("returning %d (%08x)\n", ret, GetLastError());
1812 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
1813 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1814 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1820 const CERT_AUTHORITY_KEY_ID_INFO *info =
1821 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
1822 struct AsnEncodeSequenceItem items[3] = { { 0 } };
1823 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
1824 struct AsnConstructedItem constructed = { 0 };
1825 DWORD cItem = 0, cSwapped = 0;
1827 if (info->KeyId.cbData)
1829 swapped[cSwapped].tag = ASN_CONTEXT | 0;
1830 swapped[cSwapped].pvStructInfo = &info->KeyId;
1831 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1832 items[cItem].pvStructInfo = &swapped[cSwapped];
1833 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1837 if (info->CertIssuer.cbData)
1839 constructed.tag = 1;
1840 constructed.pvStructInfo = &info->CertIssuer;
1841 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1842 items[cItem].pvStructInfo = &constructed;
1843 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1846 if (info->CertSerialNumber.cbData)
1848 swapped[cSwapped].tag = ASN_CONTEXT | 2;
1849 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
1850 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1851 items[cItem].pvStructInfo = &swapped[cSwapped];
1852 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1856 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
1857 pEncodePara, pbEncoded, pcbEncoded);
1861 SetLastError(STATUS_ACCESS_VIOLATION);
1868 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1869 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1870 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1876 const CERT_ALT_NAME_INFO *info =
1877 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1878 DWORD bytesNeeded, dataLen, lenBytes, i;
1881 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1882 * can't encode an erroneous entry index if it's bigger than this.
1884 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
1888 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
1892 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
1894 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1895 * the bad character, now set the index of the bad
1898 *pcbEncoded = (BYTE)i <<
1899 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
1904 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1905 bytesNeeded = 1 + lenBytes + dataLen;
1908 *pcbEncoded = bytesNeeded;
1913 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1914 pbEncoded, pcbEncoded, bytesNeeded)))
1916 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1917 pbEncoded = *(BYTE **)pbEncoded;
1918 *pbEncoded++ = ASN_SEQUENCEOF;
1919 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1920 pbEncoded += lenBytes;
1921 for (i = 0; ret && i < info->cAltEntry; i++)
1923 DWORD len = dataLen;
1925 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
1939 SetLastError(STATUS_ACCESS_VIOLATION);
1946 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
1947 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1948 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1954 const CERT_BASIC_CONSTRAINTS_INFO *info =
1955 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
1956 struct AsnEncodeSequenceItem items[3] = {
1957 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
1962 if (info->fPathLenConstraint)
1964 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1965 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1968 if (info->cSubtreesConstraint)
1970 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
1971 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
1974 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1975 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1979 SetLastError(STATUS_ACCESS_VIOLATION);
1986 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
1987 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1988 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1994 const CERT_BASIC_CONSTRAINTS2_INFO *info =
1995 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
1996 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2001 items[cItem].pvStructInfo = &info->fCA;
2002 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2005 if (info->fPathLenConstraint)
2007 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2008 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2011 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2012 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2016 SetLastError(STATUS_ACCESS_VIOLATION);
2023 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2024 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2025 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2031 const BLOBHEADER *hdr =
2032 (const BLOBHEADER *)pvStructInfo;
2034 if (hdr->bType != PUBLICKEYBLOB)
2036 SetLastError(E_INVALIDARG);
2041 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2042 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2043 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2044 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2045 struct AsnEncodeSequenceItem items[] = {
2046 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2047 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2050 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2051 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2057 SetLastError(STATUS_ACCESS_VIOLATION);
2064 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2065 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2066 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2072 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2073 DWORD bytesNeeded, lenBytes;
2075 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2076 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2078 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2079 bytesNeeded = 1 + lenBytes + blob->cbData;
2082 *pcbEncoded = bytesNeeded;
2087 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2088 pcbEncoded, bytesNeeded)))
2090 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2091 pbEncoded = *(BYTE **)pbEncoded;
2092 *pbEncoded++ = ASN_OCTETSTRING;
2093 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2094 pbEncoded += lenBytes;
2096 memcpy(pbEncoded, blob->pbData, blob->cbData);
2102 SetLastError(STATUS_ACCESS_VIOLATION);
2106 TRACE("returning %d (%08x)\n", ret, GetLastError());
2110 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2111 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2112 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2118 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2119 DWORD bytesNeeded, lenBytes, dataBytes;
2122 /* yep, MS allows cUnusedBits to be >= 8 */
2123 if (!blob->cUnusedBits)
2125 dataBytes = blob->cbData;
2128 else if (blob->cbData * 8 > blob->cUnusedBits)
2130 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2131 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2139 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2140 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2143 *pcbEncoded = bytesNeeded;
2148 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2149 pcbEncoded, bytesNeeded)))
2151 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2152 pbEncoded = *(BYTE **)pbEncoded;
2153 *pbEncoded++ = ASN_BITSTRING;
2154 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2155 pbEncoded += lenBytes;
2156 *pbEncoded++ = unusedBits;
2159 BYTE mask = 0xff << unusedBits;
2163 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2164 pbEncoded += dataBytes - 1;
2166 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2173 SetLastError(STATUS_ACCESS_VIOLATION);
2180 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2181 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2188 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2189 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2194 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2199 for (i = 0; i < newBlob.cbData; i++)
2200 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2206 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2207 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2208 CryptMemFree(newBlob.pbData);
2212 SetLastError(STATUS_ACCESS_VIOLATION);
2219 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2220 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2221 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2223 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2225 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2226 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2229 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2230 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2231 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2237 DWORD significantBytes, lenBytes;
2238 BYTE padByte = 0, bytesNeeded;
2240 const CRYPT_INTEGER_BLOB *blob =
2241 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2243 significantBytes = blob->cbData;
2244 if (significantBytes)
2246 if (blob->pbData[significantBytes - 1] & 0x80)
2248 /* negative, lop off leading (little-endian) 0xffs */
2249 for (; significantBytes > 0 &&
2250 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2252 if (blob->pbData[significantBytes - 1] < 0x80)
2260 /* positive, lop off leading (little-endian) zeroes */
2261 for (; significantBytes > 0 &&
2262 !blob->pbData[significantBytes - 1]; significantBytes--)
2264 if (significantBytes == 0)
2265 significantBytes = 1;
2266 if (blob->pbData[significantBytes - 1] > 0x7f)
2274 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2276 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2277 bytesNeeded = 1 + lenBytes + significantBytes;
2282 *pcbEncoded = bytesNeeded;
2287 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2288 pcbEncoded, bytesNeeded)))
2290 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2291 pbEncoded = *(BYTE **)pbEncoded;
2292 *pbEncoded++ = ASN_INTEGER;
2295 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2296 pbEncoded += lenBytes;
2297 *pbEncoded++ = padByte;
2301 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2302 pbEncoded += lenBytes;
2304 for (; significantBytes > 0; significantBytes--)
2305 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2311 SetLastError(STATUS_ACCESS_VIOLATION);
2318 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2319 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2320 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2326 DWORD significantBytes, lenBytes;
2329 const CRYPT_INTEGER_BLOB *blob =
2330 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2332 significantBytes = blob->cbData;
2333 if (significantBytes)
2335 /* positive, lop off leading (little-endian) zeroes */
2336 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2339 if (significantBytes == 0)
2340 significantBytes = 1;
2341 if (blob->pbData[significantBytes - 1] > 0x7f)
2345 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2347 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2348 bytesNeeded = 1 + lenBytes + significantBytes;
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_INTEGER;
2366 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2367 pbEncoded += lenBytes;
2372 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2373 pbEncoded += lenBytes;
2375 for (; significantBytes > 0; significantBytes--)
2376 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2382 SetLastError(STATUS_ACCESS_VIOLATION);
2389 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2390 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2391 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2393 CRYPT_INTEGER_BLOB blob;
2396 /* Encode as an unsigned integer, then change the tag to enumerated */
2397 blob.cbData = sizeof(DWORD);
2398 blob.pbData = (BYTE *)pvStructInfo;
2399 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2400 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2401 if (ret && pbEncoded)
2403 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2404 pbEncoded = *(BYTE **)pbEncoded;
2405 pbEncoded[0] = ASN_ENUMERATED;
2410 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2411 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2412 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2419 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2420 * temporary buffer because the output buffer is not NULL-terminated.
2423 static const DWORD bytesNeeded = sizeof(buf) - 1;
2427 *pcbEncoded = bytesNeeded;
2432 /* Sanity check the year, this is a two-digit year format */
2433 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2435 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2437 SetLastError(CRYPT_E_BAD_ENCODE);
2442 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2443 pbEncoded, pcbEncoded, bytesNeeded)))
2445 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2446 pbEncoded = *(BYTE **)pbEncoded;
2447 buf[0] = ASN_UTCTIME;
2448 buf[1] = bytesNeeded - 2;
2449 snprintf(buf + 2, sizeof(buf) - 2,
2450 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2451 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2452 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2453 sysTime.wMinute, sysTime.wSecond);
2454 memcpy(pbEncoded, buf, bytesNeeded);
2461 SetLastError(STATUS_ACCESS_VIOLATION);
2468 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2469 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2470 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2477 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2478 * temporary buffer because the output buffer is not NULL-terminated.
2481 static const DWORD bytesNeeded = sizeof(buf) - 1;
2485 *pcbEncoded = bytesNeeded;
2490 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2493 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2494 pcbEncoded, bytesNeeded);
2497 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2498 pbEncoded = *(BYTE **)pbEncoded;
2499 buf[0] = ASN_GENERALTIME;
2500 buf[1] = bytesNeeded - 2;
2501 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2502 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2503 sysTime.wMinute, sysTime.wSecond);
2504 memcpy(pbEncoded, buf, bytesNeeded);
2510 SetLastError(STATUS_ACCESS_VIOLATION);
2517 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2518 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2519 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2527 /* Check the year, if it's in the UTCTime range call that encode func */
2528 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2530 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2531 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2532 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2534 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2535 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2540 SetLastError(STATUS_ACCESS_VIOLATION);
2547 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2548 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2549 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2555 DWORD bytesNeeded, dataLen, lenBytes, i;
2556 const CRYPT_SEQUENCE_OF_ANY *seq =
2557 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2559 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2560 dataLen += seq->rgValue[i].cbData;
2561 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2562 bytesNeeded = 1 + lenBytes + dataLen;
2565 *pcbEncoded = bytesNeeded;
2570 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2571 pcbEncoded, bytesNeeded)))
2573 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2574 pbEncoded = *(BYTE **)pbEncoded;
2575 *pbEncoded++ = ASN_SEQUENCEOF;
2576 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2577 pbEncoded += lenBytes;
2578 for (i = 0; i < seq->cValue; i++)
2580 memcpy(pbEncoded, seq->rgValue[i].pbData,
2581 seq->rgValue[i].cbData);
2582 pbEncoded += seq->rgValue[i].cbData;
2589 SetLastError(STATUS_ACCESS_VIOLATION);
2596 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2597 BYTE *pbEncoded, DWORD *pcbEncoded)
2600 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2601 struct AsnConstructedItem constructed = { 0 };
2602 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2603 DWORD cItem = 0, cSwapped = 0;
2605 switch (distPoint->DistPointName.dwDistPointNameChoice)
2607 case CRL_DIST_POINT_NO_NAME:
2610 case CRL_DIST_POINT_FULL_NAME:
2611 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2612 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2613 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2614 constructed.tag = 0;
2615 constructed.pvStructInfo = &swapped[cSwapped];
2616 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2617 items[cItem].pvStructInfo = &constructed;
2618 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2622 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2623 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2629 if (ret && distPoint->ReasonFlags.cbData)
2631 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2632 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2633 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2634 items[cItem].pvStructInfo = &swapped[cSwapped];
2635 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2639 if (ret && distPoint->CRLIssuer.cAltEntry)
2641 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2642 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2643 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2644 items[cItem].pvStructInfo = &swapped[cSwapped];
2645 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2650 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2651 pbEncoded, pcbEncoded);
2655 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2656 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2657 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2663 const CRL_DIST_POINTS_INFO *info =
2664 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2666 if (!info->cDistPoint)
2668 SetLastError(E_INVALIDARG);
2673 DWORD bytesNeeded, dataLen, lenBytes, i;
2676 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2680 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2684 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2686 /* Have to propagate index of failing character */
2692 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2693 bytesNeeded = 1 + lenBytes + dataLen;
2696 *pcbEncoded = bytesNeeded;
2701 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2702 pbEncoded, pcbEncoded, bytesNeeded)))
2704 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2705 pbEncoded = *(BYTE **)pbEncoded;
2706 *pbEncoded++ = ASN_SEQUENCEOF;
2707 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2708 pbEncoded += lenBytes;
2709 for (i = 0; ret && i < info->cDistPoint; i++)
2711 DWORD len = dataLen;
2713 ret = CRYPT_AsnEncodeDistPoint(
2714 &info->rgDistPoint[i], pbEncoded, &len);
2728 SetLastError(STATUS_ACCESS_VIOLATION);
2735 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2736 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2737 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2743 const CERT_ENHKEY_USAGE *usage =
2744 (const CERT_ENHKEY_USAGE *)pvStructInfo;
2745 DWORD bytesNeeded = 0, lenBytes, size, i;
2748 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2750 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2751 usage->rgpszUsageIdentifier[i],
2752 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2754 bytesNeeded += size;
2756 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2757 bytesNeeded += 1 + lenBytes;
2761 *pcbEncoded = bytesNeeded;
2764 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2765 pbEncoded, pcbEncoded, bytesNeeded)))
2767 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2768 pbEncoded = *(BYTE **)pbEncoded;
2769 *pbEncoded++ = ASN_SEQUENCEOF;
2770 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2772 pbEncoded += lenBytes;
2773 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2776 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2777 usage->rgpszUsageIdentifier[i],
2778 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2783 bytesNeeded -= size;
2792 SetLastError(STATUS_ACCESS_VIOLATION);
2799 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
2800 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2801 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2807 const CRL_ISSUING_DIST_POINT *point =
2808 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
2809 struct AsnEncodeSequenceItem items[6] = { { 0 } };
2810 struct AsnConstructedItem constructed = { 0 };
2811 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
2812 DWORD cItem = 0, cSwapped = 0;
2815 switch (point->DistPointName.dwDistPointNameChoice)
2817 case CRL_DIST_POINT_NO_NAME:
2820 case CRL_DIST_POINT_FULL_NAME:
2821 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2822 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
2823 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2824 constructed.tag = 0;
2825 constructed.pvStructInfo = &swapped[cSwapped];
2826 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2827 items[cItem].pvStructInfo = &constructed;
2828 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2833 SetLastError(E_INVALIDARG);
2836 if (ret && point->fOnlyContainsUserCerts)
2838 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2839 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
2840 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
2841 items[cItem].pvStructInfo = &swapped[cSwapped];
2842 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2846 if (ret && point->fOnlyContainsCACerts)
2848 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2849 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
2850 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
2851 items[cItem].pvStructInfo = &swapped[cSwapped];
2852 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2856 if (ret && point->OnlySomeReasonFlags.cbData)
2858 swapped[cSwapped].tag = ASN_CONTEXT | 3;
2859 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
2860 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2861 items[cItem].pvStructInfo = &swapped[cSwapped];
2862 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2866 if (ret && point->fIndirectCRL)
2868 swapped[cSwapped].tag = ASN_CONTEXT | 4;
2869 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
2870 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
2871 items[cItem].pvStructInfo = &swapped[cSwapped];
2872 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2877 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2878 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2882 SetLastError(STATUS_ACCESS_VIOLATION);
2889 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2890 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
2891 void *pvEncoded, DWORD *pcbEncoded)
2893 static HCRYPTOIDFUNCSET set = NULL;
2895 CryptEncodeObjectExFunc encodeFunc = NULL;
2896 HCRYPTOIDFUNCADDR hFunc = NULL;
2898 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
2899 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
2900 pvEncoded, pcbEncoded);
2902 if (!pvEncoded && !pcbEncoded)
2904 SetLastError(ERROR_INVALID_PARAMETER);
2907 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2908 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2910 SetLastError(ERROR_FILE_NOT_FOUND);
2914 SetLastError(NOERROR);
2915 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
2916 *(BYTE **)pvEncoded = NULL;
2917 if (!HIWORD(lpszStructType))
2919 switch (LOWORD(lpszStructType))
2921 case (WORD)X509_CERT:
2922 encodeFunc = CRYPT_AsnEncodeCert;
2924 case (WORD)X509_CERT_TO_BE_SIGNED:
2925 encodeFunc = CRYPT_AsnEncodeCertInfo;
2927 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2928 encodeFunc = CRYPT_AsnEncodeCRLInfo;
2930 case (WORD)X509_EXTENSIONS:
2931 encodeFunc = CRYPT_AsnEncodeExtensions;
2933 case (WORD)X509_NAME_VALUE:
2934 encodeFunc = CRYPT_AsnEncodeNameValue;
2936 case (WORD)X509_NAME:
2937 encodeFunc = CRYPT_AsnEncodeName;
2939 case (WORD)X509_PUBLIC_KEY_INFO:
2940 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
2942 case (WORD)X509_AUTHORITY_KEY_ID:
2943 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
2945 case (WORD)X509_ALTERNATE_NAME:
2946 encodeFunc = CRYPT_AsnEncodeAltName;
2948 case (WORD)X509_BASIC_CONSTRAINTS:
2949 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
2951 case (WORD)X509_BASIC_CONSTRAINTS2:
2952 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2954 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2955 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
2957 case (WORD)X509_UNICODE_NAME:
2958 encodeFunc = CRYPT_AsnEncodeUnicodeName;
2960 case (WORD)X509_UNICODE_NAME_VALUE:
2961 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
2963 case (WORD)X509_OCTET_STRING:
2964 encodeFunc = CRYPT_AsnEncodeOctets;
2966 case (WORD)X509_BITS:
2967 case (WORD)X509_KEY_USAGE:
2968 encodeFunc = CRYPT_AsnEncodeBits;
2970 case (WORD)X509_INTEGER:
2971 encodeFunc = CRYPT_AsnEncodeInt;
2973 case (WORD)X509_MULTI_BYTE_INTEGER:
2974 encodeFunc = CRYPT_AsnEncodeInteger;
2976 case (WORD)X509_MULTI_BYTE_UINT:
2977 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
2979 case (WORD)X509_ENUMERATED:
2980 encodeFunc = CRYPT_AsnEncodeEnumerated;
2982 case (WORD)X509_CHOICE_OF_TIME:
2983 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
2985 case (WORD)X509_SEQUENCE_OF_ANY:
2986 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2988 case (WORD)PKCS_UTC_TIME:
2989 encodeFunc = CRYPT_AsnEncodeUtcTime;
2991 case (WORD)X509_CRL_DIST_POINTS:
2992 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
2994 case (WORD)X509_ENHANCED_KEY_USAGE:
2995 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
2997 case (WORD)X509_ISSUING_DIST_POINT:
2998 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3001 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3004 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3005 encodeFunc = CRYPT_AsnEncodeExtensions;
3006 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3007 encodeFunc = CRYPT_AsnEncodeUtcTime;
3008 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3009 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3010 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3011 encodeFunc = CRYPT_AsnEncodeEnumerated;
3012 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3013 encodeFunc = CRYPT_AsnEncodeBits;
3014 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3015 encodeFunc = CRYPT_AsnEncodeOctets;
3016 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3017 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3018 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3019 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3020 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3021 encodeFunc = CRYPT_AsnEncodeAltName;
3022 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3023 encodeFunc = CRYPT_AsnEncodeAltName;
3024 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3025 encodeFunc = CRYPT_AsnEncodeAltName;
3026 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3027 encodeFunc = CRYPT_AsnEncodeAltName;
3028 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3029 encodeFunc = CRYPT_AsnEncodeAltName;
3030 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3031 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3032 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3033 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3034 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3035 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3037 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3038 debugstr_a(lpszStructType));
3042 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3043 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3044 (void **)&encodeFunc, &hFunc);
3047 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3048 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3050 SetLastError(ERROR_FILE_NOT_FOUND);
3052 CryptFreeOIDFunctionAddress(hFunc, 0);
3056 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3057 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3059 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3060 NULL, 0, NULL, pInfo, pcbInfo);
3063 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3064 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3065 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3069 static CHAR oid[] = szOID_RSA_RSA;
3071 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3072 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3075 if (!pszPublicKeyObjId)
3076 pszPublicKeyObjId = oid;
3077 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3081 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3084 LPBYTE pubKey = CryptMemAlloc(keySize);
3088 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3092 DWORD encodedLen = 0;
3094 ret = CryptEncodeObject(dwCertEncodingType,
3095 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3098 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3099 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3102 *pcbInfo = sizeNeeded;
3103 else if (*pcbInfo < sizeNeeded)
3105 SetLastError(ERROR_MORE_DATA);
3106 *pcbInfo = sizeNeeded;
3111 pInfo->Algorithm.pszObjId = (char *)pInfo +
3112 sizeof(CERT_PUBLIC_KEY_INFO);
3113 lstrcpyA(pInfo->Algorithm.pszObjId,
3115 pInfo->Algorithm.Parameters.cbData = 0;
3116 pInfo->Algorithm.Parameters.pbData = NULL;
3117 pInfo->PublicKey.pbData =
3118 (BYTE *)pInfo->Algorithm.pszObjId
3119 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3120 pInfo->PublicKey.cbData = encodedLen;
3121 pInfo->PublicKey.cUnusedBits = 0;
3122 ret = CryptEncodeObject(dwCertEncodingType,
3123 RSA_CSP_PUBLICKEYBLOB, pubKey,
3124 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3128 CryptMemFree(pubKey);
3133 CryptDestroyKey(key);
3138 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3139 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3140 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3142 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3143 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3144 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3146 static HCRYPTOIDFUNCSET set = NULL;
3148 ExportPublicKeyInfoExFunc exportFunc = NULL;
3149 HCRYPTOIDFUNCADDR hFunc = NULL;
3151 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3152 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3157 SetLastError(ERROR_INVALID_PARAMETER);
3161 if (pszPublicKeyObjId)
3164 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3166 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3167 0, (void **)&exportFunc, &hFunc);
3170 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3171 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3172 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3174 CryptFreeOIDFunctionAddress(hFunc, 0);
3178 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3179 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3181 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3185 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3186 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3187 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3190 DWORD pubKeySize = 0;
3192 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3193 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3195 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3196 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3199 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3203 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3204 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3207 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3209 CryptMemFree(pubKey);
3217 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3218 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3219 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3221 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3222 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3223 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3225 static HCRYPTOIDFUNCSET set = NULL;
3227 ImportPublicKeyInfoExFunc importFunc = NULL;
3228 HCRYPTOIDFUNCADDR hFunc = NULL;
3230 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3231 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3234 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3235 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3236 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3238 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3239 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3242 CryptFreeOIDFunctionAddress(hFunc, 0);