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%08lx, %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, %ld, %08lx, %p, %p, %ld\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 (%08lx)\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 (%08lx)\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 **)
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, %ld\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 (%08lx)\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 = (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 CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1099 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1103 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1104 DWORD bytesNeeded, lenBytes, encodedLen;
1106 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1108 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1109 bytesNeeded = 1 + lenBytes + encodedLen;
1111 *pcbEncoded = bytesNeeded;
1114 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1115 pbEncoded, pcbEncoded, bytesNeeded)))
1119 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1120 pbEncoded = *(BYTE **)pbEncoded;
1122 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1123 pbEncoded += lenBytes;
1124 for (i = 0; i < encodedLen; i++)
1125 *pbEncoded++ = (BYTE)str[i];
1131 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1132 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1136 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1137 DWORD bytesNeeded, lenBytes, encodedLen;
1139 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1141 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1142 bytesNeeded = 1 + lenBytes + encodedLen;
1144 *pcbEncoded = bytesNeeded;
1147 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1148 pbEncoded, pcbEncoded, bytesNeeded)))
1152 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1153 pbEncoded = *(BYTE **)pbEncoded;
1154 *pbEncoded++ = ASN_NUMERICSTRING;
1155 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1156 pbEncoded += lenBytes;
1157 for (i = 0; ret && i < encodedLen; i++)
1159 if (isdigitW(str[i]))
1160 *pbEncoded++ = (BYTE)str[i];
1164 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1173 static inline int isprintableW(WCHAR wc)
1175 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1176 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1177 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1180 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1181 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1185 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1186 DWORD bytesNeeded, lenBytes, encodedLen;
1188 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1190 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1191 bytesNeeded = 1 + lenBytes + encodedLen;
1193 *pcbEncoded = bytesNeeded;
1196 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1197 pbEncoded, pcbEncoded, bytesNeeded)))
1201 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1202 pbEncoded = *(BYTE **)pbEncoded;
1203 *pbEncoded++ = ASN_PRINTABLESTRING;
1204 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1205 pbEncoded += lenBytes;
1206 for (i = 0; ret && i < encodedLen; i++)
1208 if (isprintableW(str[i]))
1209 *pbEncoded++ = (BYTE)str[i];
1213 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1222 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1223 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1227 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1228 DWORD bytesNeeded, lenBytes, encodedLen;
1230 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1232 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1233 bytesNeeded = 1 + lenBytes + encodedLen;
1235 *pcbEncoded = bytesNeeded;
1238 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1239 pbEncoded, pcbEncoded, bytesNeeded)))
1243 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1244 pbEncoded = *(BYTE **)pbEncoded;
1245 *pbEncoded++ = ASN_IA5STRING;
1246 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1247 pbEncoded += lenBytes;
1248 for (i = 0; ret && i < encodedLen; i++)
1251 *pbEncoded++ = (BYTE)str[i];
1255 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1264 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1265 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1269 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1270 DWORD bytesNeeded, lenBytes, strLen;
1272 /* FIXME: doesn't handle composite characters */
1273 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1275 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1276 bytesNeeded = 1 + lenBytes + strLen * 4;
1278 *pcbEncoded = bytesNeeded;
1281 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1282 pbEncoded, pcbEncoded, bytesNeeded)))
1286 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1287 pbEncoded = *(BYTE **)pbEncoded;
1288 *pbEncoded++ = ASN_UNIVERSALSTRING;
1289 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1290 pbEncoded += lenBytes;
1291 for (i = 0; i < strLen; i++)
1295 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1296 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1303 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1304 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1305 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1311 const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1313 switch (value->dwValueType)
1315 case CERT_RDN_ANY_TYPE:
1316 case CERT_RDN_ENCODED_BLOB:
1317 case CERT_RDN_OCTET_STRING:
1318 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1320 case CERT_RDN_NUMERIC_STRING:
1321 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1322 pbEncoded, pcbEncoded);
1324 case CERT_RDN_PRINTABLE_STRING:
1325 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1326 pbEncoded, pcbEncoded);
1328 case CERT_RDN_TELETEX_STRING:
1329 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1330 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1332 case CERT_RDN_VIDEOTEX_STRING:
1333 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1334 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1336 case CERT_RDN_IA5_STRING:
1337 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1338 pbEncoded, pcbEncoded);
1340 case CERT_RDN_GRAPHIC_STRING:
1341 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1342 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1344 case CERT_RDN_VISIBLE_STRING:
1345 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1346 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1348 case CERT_RDN_GENERAL_STRING:
1349 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1350 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1352 case CERT_RDN_UNIVERSAL_STRING:
1353 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1354 pbEncoded, pcbEncoded);
1356 case CERT_RDN_BMP_STRING:
1357 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1358 pbEncoded, pcbEncoded);
1360 case CERT_RDN_UTF8_STRING:
1361 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1362 pbEncoded, pcbEncoded);
1365 SetLastError(CRYPT_E_ASN1_CHOICE);
1370 SetLastError(STATUS_ACCESS_VIOLATION);
1376 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1377 CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
1379 DWORD bytesNeeded = 0, lenBytes, size;
1382 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1383 0, NULL, NULL, &size);
1386 bytesNeeded += size;
1387 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1388 * with dwValueType, so "cast" it to get its encoded size
1390 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType, X509_NAME_VALUE,
1391 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1394 bytesNeeded += size;
1395 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1396 bytesNeeded += 1 + lenBytes;
1399 if (*pcbEncoded < bytesNeeded)
1401 SetLastError(ERROR_MORE_DATA);
1406 *pbEncoded++ = ASN_SEQUENCE;
1407 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1409 pbEncoded += lenBytes;
1410 size = bytesNeeded - 1 - lenBytes;
1411 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1412 attr->pszObjId, 0, NULL, pbEncoded, &size);
1416 size = bytesNeeded - 1 - lenBytes - size;
1417 ret = CRYPT_AsnEncodeNameValue(dwCertEncodingType,
1418 X509_NAME_VALUE, (CERT_NAME_VALUE *)&attr->dwValueType,
1419 0, NULL, pbEncoded, &size);
1423 *pcbEncoded = bytesNeeded;
1429 static int BLOBComp(const void *l, const void *r)
1431 CRYPT_DER_BLOB *a = (CRYPT_DER_BLOB *)l, *b = (CRYPT_DER_BLOB *)r;
1434 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1435 ret = a->cbData - b->cbData;
1439 /* This encodes as a SET OF, which in DER must be lexicographically sorted.
1441 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1442 BYTE *pbEncoded, DWORD *pcbEncoded)
1445 CRYPT_DER_BLOB *blobs = NULL;
1449 DWORD bytesNeeded = 0, lenBytes, i;
1455 blobs = CryptMemAlloc(rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1459 memset(blobs, 0, rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
1461 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1463 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1464 NULL, &blobs[i].cbData);
1466 bytesNeeded += blobs[i].cbData;
1470 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1471 bytesNeeded += 1 + lenBytes;
1474 if (*pcbEncoded < bytesNeeded)
1476 SetLastError(ERROR_MORE_DATA);
1481 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1483 blobs[i].pbData = CryptMemAlloc(blobs[i].cbData);
1484 if (!blobs[i].pbData)
1487 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1488 &rdn->rgRDNAttr[i], blobs[i].pbData,
1493 qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
1495 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1496 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1498 pbEncoded += lenBytes;
1499 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1501 memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
1502 pbEncoded += blobs[i].cbData;
1507 *pcbEncoded = bytesNeeded;
1511 for (i = 0; i < rdn->cRDNAttr; i++)
1512 CryptMemFree(blobs[i].pbData);
1517 SetLastError(STATUS_ACCESS_VIOLATION);
1521 CryptMemFree(blobs);
1525 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1526 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1527 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1533 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1534 DWORD bytesNeeded = 0, lenBytes, size, i;
1536 TRACE("encoding name with %ld RDNs\n", info->cRDN);
1538 for (i = 0; ret && i < info->cRDN; i++)
1540 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
1543 bytesNeeded += size;
1545 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1546 bytesNeeded += 1 + lenBytes;
1550 *pcbEncoded = bytesNeeded;
1553 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1554 pbEncoded, pcbEncoded, bytesNeeded)))
1556 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1557 pbEncoded = *(BYTE **)pbEncoded;
1558 *pbEncoded++ = ASN_SEQUENCEOF;
1559 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1561 pbEncoded += lenBytes;
1562 for (i = 0; ret && i < info->cRDN; i++)
1565 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1566 &info->rgRDN[i], pbEncoded, &size);
1570 bytesNeeded -= size;
1579 SetLastError(STATUS_ACCESS_VIOLATION);
1586 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1587 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1588 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1590 BOOL val = *(const BOOL *)pvStructInfo, ret;
1599 else if (*pcbEncoded < 3)
1602 SetLastError(ERROR_MORE_DATA);
1608 *pbEncoded++ = ASN_BOOL;
1610 *pbEncoded++ = val ? 0xff : 0;
1613 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1617 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1618 BYTE *pbEncoded, DWORD *pcbEncoded)
1624 switch (entry->dwAltNameChoice)
1626 case CERT_ALT_NAME_RFC822_NAME:
1627 case CERT_ALT_NAME_DNS_NAME:
1628 case CERT_ALT_NAME_URL:
1629 if (entry->u.pwszURL)
1633 /* Not + 1: don't encode the NULL-terminator */
1634 dataLen = lstrlenW(entry->u.pwszURL);
1635 for (i = 0; ret && i < dataLen; i++)
1637 if (entry->u.pwszURL[i] > 0x7f)
1639 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1648 case CERT_ALT_NAME_IP_ADDRESS:
1649 dataLen = entry->u.IPAddress.cbData;
1651 case CERT_ALT_NAME_REGISTERED_ID:
1652 /* FIXME: encode OID */
1653 case CERT_ALT_NAME_OTHER_NAME:
1654 case CERT_ALT_NAME_DIRECTORY_NAME:
1655 FIXME("name type %ld unimplemented\n", entry->dwAltNameChoice);
1658 SetLastError(E_INVALIDARG);
1663 DWORD bytesNeeded, lenBytes;
1665 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1666 bytesNeeded = 1 + dataLen + lenBytes;
1668 *pcbEncoded = bytesNeeded;
1669 else if (*pcbEncoded < bytesNeeded)
1671 SetLastError(ERROR_MORE_DATA);
1672 *pcbEncoded = bytesNeeded;
1677 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1678 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1679 pbEncoded += lenBytes;
1680 switch (entry->dwAltNameChoice)
1682 case CERT_ALT_NAME_RFC822_NAME:
1683 case CERT_ALT_NAME_DNS_NAME:
1684 case CERT_ALT_NAME_URL:
1688 for (i = 0; i < dataLen; i++)
1689 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1692 case CERT_ALT_NAME_IP_ADDRESS:
1693 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1697 *pcbEncoded = bytesNeeded;
1700 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1704 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
1705 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1706 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1712 const CERT_ALT_NAME_INFO *info =
1713 (const CERT_ALT_NAME_INFO *)pvStructInfo;
1714 DWORD bytesNeeded, dataLen, lenBytes, i;
1717 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
1718 * can't encode an erroneous entry index if it's bigger than this.
1720 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
1724 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
1728 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
1730 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
1731 * the bad character, now set the index of the bad
1734 *pcbEncoded = (BYTE)i <<
1735 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
1740 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1741 bytesNeeded = 1 + lenBytes + dataLen;
1744 *pcbEncoded = bytesNeeded;
1749 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1750 pbEncoded, pcbEncoded, bytesNeeded)))
1752 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1753 pbEncoded = *(BYTE **)pbEncoded;
1754 *pbEncoded++ = ASN_SEQUENCEOF;
1755 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1756 pbEncoded += lenBytes;
1757 for (i = 0; ret && i < info->cAltEntry; i++)
1759 DWORD len = dataLen;
1761 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
1775 SetLastError(STATUS_ACCESS_VIOLATION);
1782 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
1783 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1784 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1790 const CERT_BASIC_CONSTRAINTS_INFO *info =
1791 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
1792 struct AsnEncodeSequenceItem items[3] = {
1793 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
1798 if (info->fPathLenConstraint)
1800 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1801 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1804 if (info->cSubtreesConstraint)
1806 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
1807 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
1810 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1811 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1815 SetLastError(STATUS_ACCESS_VIOLATION);
1822 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
1823 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1824 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1830 const CERT_BASIC_CONSTRAINTS2_INFO *info =
1831 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
1832 struct AsnEncodeSequenceItem items[2] = { { 0 } };
1837 items[cItem].pvStructInfo = &info->fCA;
1838 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
1841 if (info->fPathLenConstraint)
1843 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
1844 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
1847 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1848 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1852 SetLastError(STATUS_ACCESS_VIOLATION);
1859 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
1860 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1861 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1867 const BLOBHEADER *hdr =
1868 (const BLOBHEADER *)pvStructInfo;
1870 if (hdr->bType != PUBLICKEYBLOB)
1872 SetLastError(E_INVALIDARG);
1877 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
1878 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
1879 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
1880 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
1881 struct AsnEncodeSequenceItem items[] = {
1882 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
1883 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
1886 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1887 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1893 SetLastError(STATUS_ACCESS_VIOLATION);
1900 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
1901 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1902 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1908 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
1909 DWORD bytesNeeded, lenBytes;
1911 TRACE("(%ld, %p), %08lx, %p, %p, %ld\n", blob->cbData, blob->pbData,
1912 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
1914 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
1915 bytesNeeded = 1 + lenBytes + blob->cbData;
1918 *pcbEncoded = bytesNeeded;
1923 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1924 pcbEncoded, bytesNeeded)))
1926 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1927 pbEncoded = *(BYTE **)pbEncoded;
1928 *pbEncoded++ = ASN_OCTETSTRING;
1929 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
1930 pbEncoded += lenBytes;
1932 memcpy(pbEncoded, blob->pbData, blob->cbData);
1938 SetLastError(STATUS_ACCESS_VIOLATION);
1942 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1946 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
1947 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1948 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1954 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
1955 DWORD bytesNeeded, lenBytes, dataBytes;
1958 /* yep, MS allows cUnusedBits to be >= 8 */
1959 if (!blob->cUnusedBits)
1961 dataBytes = blob->cbData;
1964 else if (blob->cbData * 8 > blob->cUnusedBits)
1966 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
1967 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
1975 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
1976 bytesNeeded = 1 + lenBytes + dataBytes + 1;
1979 *pcbEncoded = bytesNeeded;
1984 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1985 pcbEncoded, bytesNeeded)))
1987 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1988 pbEncoded = *(BYTE **)pbEncoded;
1989 *pbEncoded++ = ASN_BITSTRING;
1990 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
1991 pbEncoded += lenBytes;
1992 *pbEncoded++ = unusedBits;
1995 BYTE mask = 0xff << unusedBits;
1999 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2000 pbEncoded += dataBytes - 1;
2002 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2009 SetLastError(STATUS_ACCESS_VIOLATION);
2016 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2017 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2018 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2024 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2025 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2030 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2035 for (i = 0; i < newBlob.cbData; i++)
2036 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2042 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2043 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2044 CryptMemFree(newBlob.pbData);
2048 SetLastError(STATUS_ACCESS_VIOLATION);
2055 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2056 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2057 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2059 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2061 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2062 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2065 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2066 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2067 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2073 DWORD significantBytes, lenBytes;
2074 BYTE padByte = 0, bytesNeeded;
2076 const CRYPT_INTEGER_BLOB *blob =
2077 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2079 significantBytes = blob->cbData;
2080 if (significantBytes)
2082 if (blob->pbData[significantBytes - 1] & 0x80)
2084 /* negative, lop off leading (little-endian) 0xffs */
2085 for (; significantBytes > 0 &&
2086 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2088 if (blob->pbData[significantBytes - 1] < 0x80)
2096 /* positive, lop off leading (little-endian) zeroes */
2097 for (; significantBytes > 0 &&
2098 !blob->pbData[significantBytes - 1]; significantBytes--)
2100 if (significantBytes == 0)
2101 significantBytes = 1;
2102 if (blob->pbData[significantBytes - 1] > 0x7f)
2110 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2112 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2113 bytesNeeded = 1 + lenBytes + significantBytes;
2118 *pcbEncoded = bytesNeeded;
2123 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2124 pcbEncoded, bytesNeeded)))
2126 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2127 pbEncoded = *(BYTE **)pbEncoded;
2128 *pbEncoded++ = ASN_INTEGER;
2131 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2132 pbEncoded += lenBytes;
2133 *pbEncoded++ = padByte;
2137 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2138 pbEncoded += lenBytes;
2140 for (; significantBytes > 0; significantBytes--)
2141 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2147 SetLastError(STATUS_ACCESS_VIOLATION);
2154 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2155 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2156 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2162 DWORD significantBytes, lenBytes;
2165 const CRYPT_INTEGER_BLOB *blob =
2166 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2168 significantBytes = blob->cbData;
2169 if (significantBytes)
2171 /* positive, lop off leading (little-endian) zeroes */
2172 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2175 if (significantBytes == 0)
2176 significantBytes = 1;
2177 if (blob->pbData[significantBytes - 1] > 0x7f)
2181 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2183 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2184 bytesNeeded = 1 + lenBytes + significantBytes;
2189 *pcbEncoded = bytesNeeded;
2194 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2195 pcbEncoded, bytesNeeded)))
2197 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2198 pbEncoded = *(BYTE **)pbEncoded;
2199 *pbEncoded++ = ASN_INTEGER;
2202 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2203 pbEncoded += lenBytes;
2208 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2209 pbEncoded += lenBytes;
2211 for (; significantBytes > 0; significantBytes--)
2212 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2218 SetLastError(STATUS_ACCESS_VIOLATION);
2225 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2226 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2227 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2229 CRYPT_INTEGER_BLOB blob;
2232 /* Encode as an unsigned integer, then change the tag to enumerated */
2233 blob.cbData = sizeof(DWORD);
2234 blob.pbData = (BYTE *)pvStructInfo;
2235 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2236 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2237 if (ret && pbEncoded)
2239 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2240 pbEncoded = *(BYTE **)pbEncoded;
2241 pbEncoded[0] = ASN_ENUMERATED;
2246 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2247 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2248 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2255 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2256 * temporary buffer because the output buffer is not NULL-terminated.
2259 static const DWORD bytesNeeded = sizeof(buf) - 1;
2263 *pcbEncoded = bytesNeeded;
2268 /* Sanity check the year, this is a two-digit year format */
2269 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2271 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2273 SetLastError(CRYPT_E_BAD_ENCODE);
2278 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2279 pbEncoded, pcbEncoded, bytesNeeded)))
2281 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2282 pbEncoded = *(BYTE **)pbEncoded;
2283 buf[0] = ASN_UTCTIME;
2284 buf[1] = bytesNeeded - 2;
2285 snprintf(buf + 2, sizeof(buf) - 2,
2286 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2287 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2288 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2289 sysTime.wMinute, sysTime.wSecond);
2290 memcpy(pbEncoded, buf, bytesNeeded);
2297 SetLastError(STATUS_ACCESS_VIOLATION);
2304 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2305 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2306 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2313 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2314 * temporary buffer because the output buffer is not NULL-terminated.
2317 static const DWORD bytesNeeded = sizeof(buf) - 1;
2321 *pcbEncoded = bytesNeeded;
2326 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2329 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2330 pcbEncoded, bytesNeeded);
2333 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2334 pbEncoded = *(BYTE **)pbEncoded;
2335 buf[0] = ASN_GENERALTIME;
2336 buf[1] = bytesNeeded - 2;
2337 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2338 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2339 sysTime.wMinute, sysTime.wSecond);
2340 memcpy(pbEncoded, buf, bytesNeeded);
2346 SetLastError(STATUS_ACCESS_VIOLATION);
2353 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2354 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2355 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2363 /* Check the year, if it's in the UTCTime range call that encode func */
2364 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2366 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2367 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2368 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2370 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2371 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2376 SetLastError(STATUS_ACCESS_VIOLATION);
2383 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2384 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2385 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2391 DWORD bytesNeeded, dataLen, lenBytes, i;
2392 const CRYPT_SEQUENCE_OF_ANY *seq =
2393 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2395 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2396 dataLen += seq->rgValue[i].cbData;
2397 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2398 bytesNeeded = 1 + lenBytes + dataLen;
2401 *pcbEncoded = bytesNeeded;
2406 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2407 pcbEncoded, bytesNeeded)))
2409 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2410 pbEncoded = *(BYTE **)pbEncoded;
2411 *pbEncoded++ = ASN_SEQUENCEOF;
2412 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2413 pbEncoded += lenBytes;
2414 for (i = 0; i < seq->cValue; i++)
2416 memcpy(pbEncoded, seq->rgValue[i].pbData,
2417 seq->rgValue[i].cbData);
2418 pbEncoded += seq->rgValue[i].cbData;
2425 SetLastError(STATUS_ACCESS_VIOLATION);
2432 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2433 BYTE *pbEncoded, DWORD *pcbEncoded)
2436 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2437 struct AsnConstructedItem constructed = { 0 };
2438 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2439 DWORD cItem = 0, cSwapped = 0;
2441 switch (distPoint->DistPointName.dwDistPointNameChoice)
2443 case CRL_DIST_POINT_NO_NAME:
2446 case CRL_DIST_POINT_FULL_NAME:
2447 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2448 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2449 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2450 constructed.tag = 0;
2451 constructed.pvStructInfo = &swapped[cSwapped];
2452 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2453 items[cItem].pvStructInfo = &constructed;
2454 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2458 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2459 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2465 if (ret && distPoint->ReasonFlags.cbData)
2467 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2468 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2469 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2470 items[cItem].pvStructInfo = &swapped[cSwapped];
2471 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2475 if (ret && distPoint->CRLIssuer.cAltEntry)
2477 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2478 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2479 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2480 items[cItem].pvStructInfo = &swapped[cSwapped];
2481 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2486 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2487 pbEncoded, pcbEncoded);
2491 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2492 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2493 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2499 const CRL_DIST_POINTS_INFO *info =
2500 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2502 if (!info->cDistPoint)
2504 SetLastError(E_INVALIDARG);
2509 DWORD bytesNeeded, dataLen, lenBytes, i;
2512 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2516 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2520 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2522 /* Have to propagate index of failing character */
2528 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2529 bytesNeeded = 1 + lenBytes + dataLen;
2532 *pcbEncoded = bytesNeeded;
2537 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2538 pbEncoded, pcbEncoded, bytesNeeded)))
2540 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2541 pbEncoded = *(BYTE **)pbEncoded;
2542 *pbEncoded++ = ASN_SEQUENCEOF;
2543 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2544 pbEncoded += lenBytes;
2545 for (i = 0; ret && i < info->cDistPoint; i++)
2547 DWORD len = dataLen;
2549 ret = CRYPT_AsnEncodeDistPoint(
2550 &info->rgDistPoint[i], pbEncoded, &len);
2564 SetLastError(STATUS_ACCESS_VIOLATION);
2571 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2572 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2573 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2579 const CERT_ENHKEY_USAGE *usage =
2580 (const CERT_ENHKEY_USAGE *)pvStructInfo;
2581 DWORD bytesNeeded = 0, lenBytes, size, i;
2584 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2586 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2587 usage->rgpszUsageIdentifier[i],
2588 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2590 bytesNeeded += size;
2592 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2593 bytesNeeded += 1 + lenBytes;
2597 *pcbEncoded = bytesNeeded;
2600 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2601 pbEncoded, pcbEncoded, bytesNeeded)))
2603 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2604 pbEncoded = *(BYTE **)pbEncoded;
2605 *pbEncoded++ = ASN_SEQUENCEOF;
2606 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2608 pbEncoded += lenBytes;
2609 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2612 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2613 usage->rgpszUsageIdentifier[i],
2614 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2619 bytesNeeded -= size;
2628 SetLastError(STATUS_ACCESS_VIOLATION);
2635 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
2636 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2637 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2643 const CRL_ISSUING_DIST_POINT *point =
2644 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
2645 struct AsnEncodeSequenceItem items[6] = { { 0 } };
2646 struct AsnConstructedItem constructed = { 0 };
2647 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
2648 DWORD cItem = 0, cSwapped = 0;
2651 switch (point->DistPointName.dwDistPointNameChoice)
2653 case CRL_DIST_POINT_NO_NAME:
2656 case CRL_DIST_POINT_FULL_NAME:
2657 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2658 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
2659 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2660 constructed.tag = 0;
2661 constructed.pvStructInfo = &swapped[cSwapped];
2662 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2663 items[cItem].pvStructInfo = &constructed;
2664 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2669 SetLastError(E_INVALIDARG);
2672 if (ret && point->fOnlyContainsUserCerts)
2674 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2675 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
2676 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
2677 items[cItem].pvStructInfo = &swapped[cSwapped];
2678 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2682 if (ret && point->fOnlyContainsCACerts)
2684 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2685 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
2686 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
2687 items[cItem].pvStructInfo = &swapped[cSwapped];
2688 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2692 if (ret && point->OnlySomeReasonFlags.cbData)
2694 swapped[cSwapped].tag = ASN_CONTEXT | 3;
2695 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
2696 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2697 items[cItem].pvStructInfo = &swapped[cSwapped];
2698 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2702 if (ret && point->fIndirectCRL)
2704 swapped[cSwapped].tag = ASN_CONTEXT | 4;
2705 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
2706 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
2707 items[cItem].pvStructInfo = &swapped[cSwapped];
2708 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2713 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2714 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2718 SetLastError(STATUS_ACCESS_VIOLATION);
2725 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2726 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
2727 void *pvEncoded, DWORD *pcbEncoded)
2729 static HCRYPTOIDFUNCSET set = NULL;
2731 CryptEncodeObjectExFunc encodeFunc = NULL;
2732 HCRYPTOIDFUNCADDR hFunc = NULL;
2734 TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p)\n", dwCertEncodingType,
2735 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
2736 pvEncoded, pcbEncoded);
2738 if (!pvEncoded && !pcbEncoded)
2740 SetLastError(ERROR_INVALID_PARAMETER);
2743 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2744 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2746 SetLastError(ERROR_FILE_NOT_FOUND);
2750 SetLastError(NOERROR);
2751 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
2752 *(BYTE **)pvEncoded = NULL;
2753 if (!HIWORD(lpszStructType))
2755 switch (LOWORD(lpszStructType))
2757 case (WORD)X509_CERT:
2758 encodeFunc = CRYPT_AsnEncodeCert;
2760 case (WORD)X509_CERT_TO_BE_SIGNED:
2761 encodeFunc = CRYPT_AsnEncodeCertInfo;
2763 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2764 encodeFunc = CRYPT_AsnEncodeCRLInfo;
2766 case (WORD)X509_EXTENSIONS:
2767 encodeFunc = CRYPT_AsnEncodeExtensions;
2769 case (WORD)X509_NAME_VALUE:
2770 encodeFunc = CRYPT_AsnEncodeNameValue;
2772 case (WORD)X509_NAME:
2773 encodeFunc = CRYPT_AsnEncodeName;
2775 case (WORD)X509_PUBLIC_KEY_INFO:
2776 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
2778 case (WORD)X509_ALTERNATE_NAME:
2779 encodeFunc = CRYPT_AsnEncodeAltName;
2781 case (WORD)X509_BASIC_CONSTRAINTS:
2782 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
2784 case (WORD)X509_BASIC_CONSTRAINTS2:
2785 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2787 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2788 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
2790 case (WORD)X509_UNICODE_NAME_VALUE:
2791 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
2793 case (WORD)X509_OCTET_STRING:
2794 encodeFunc = CRYPT_AsnEncodeOctets;
2796 case (WORD)X509_BITS:
2797 case (WORD)X509_KEY_USAGE:
2798 encodeFunc = CRYPT_AsnEncodeBits;
2800 case (WORD)X509_INTEGER:
2801 encodeFunc = CRYPT_AsnEncodeInt;
2803 case (WORD)X509_MULTI_BYTE_INTEGER:
2804 encodeFunc = CRYPT_AsnEncodeInteger;
2806 case (WORD)X509_MULTI_BYTE_UINT:
2807 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
2809 case (WORD)X509_ENUMERATED:
2810 encodeFunc = CRYPT_AsnEncodeEnumerated;
2812 case (WORD)X509_CHOICE_OF_TIME:
2813 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
2815 case (WORD)X509_SEQUENCE_OF_ANY:
2816 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2818 case (WORD)PKCS_UTC_TIME:
2819 encodeFunc = CRYPT_AsnEncodeUtcTime;
2821 case (WORD)X509_CRL_DIST_POINTS:
2822 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
2824 case (WORD)X509_ENHANCED_KEY_USAGE:
2825 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
2827 case (WORD)X509_ISSUING_DIST_POINT:
2828 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
2831 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
2834 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
2835 encodeFunc = CRYPT_AsnEncodeExtensions;
2836 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
2837 encodeFunc = CRYPT_AsnEncodeUtcTime;
2838 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
2839 encodeFunc = CRYPT_AsnEncodeEnumerated;
2840 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2841 encodeFunc = CRYPT_AsnEncodeBits;
2842 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
2843 encodeFunc = CRYPT_AsnEncodeOctets;
2844 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
2845 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
2846 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2847 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
2848 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2849 encodeFunc = CRYPT_AsnEncodeAltName;
2850 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2851 encodeFunc = CRYPT_AsnEncodeAltName;
2852 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
2853 encodeFunc = CRYPT_AsnEncodeAltName;
2854 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2855 encodeFunc = CRYPT_AsnEncodeAltName;
2856 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2857 encodeFunc = CRYPT_AsnEncodeAltName;
2858 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
2859 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
2860 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
2861 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
2862 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
2863 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
2865 TRACE("OID %s not found or unimplemented, looking for DLL\n",
2866 debugstr_a(lpszStructType));
2870 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
2871 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2872 (void **)&encodeFunc, &hFunc);
2875 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
2876 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
2878 SetLastError(ERROR_FILE_NOT_FOUND);
2880 CryptFreeOIDFunctionAddress(hFunc, 0);
2884 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
2885 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
2887 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
2888 NULL, 0, NULL, pInfo, pcbInfo);
2891 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
2892 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
2893 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
2897 static CHAR oid[] = szOID_RSA_RSA;
2899 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
2900 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
2903 if (!pszPublicKeyObjId)
2904 pszPublicKeyObjId = oid;
2905 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
2909 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
2912 LPBYTE pubKey = CryptMemAlloc(keySize);
2916 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
2920 DWORD encodedLen = 0;
2922 ret = CryptEncodeObject(dwCertEncodingType,
2923 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
2926 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
2927 strlen(pszPublicKeyObjId) + 1 + encodedLen;
2930 *pcbInfo = sizeNeeded;
2931 else if (*pcbInfo < sizeNeeded)
2933 SetLastError(ERROR_MORE_DATA);
2934 *pcbInfo = sizeNeeded;
2939 pInfo->Algorithm.pszObjId = (char *)pInfo +
2940 sizeof(CERT_PUBLIC_KEY_INFO);
2941 lstrcpyA(pInfo->Algorithm.pszObjId,
2943 pInfo->Algorithm.Parameters.cbData = 0;
2944 pInfo->Algorithm.Parameters.pbData = NULL;
2945 pInfo->PublicKey.pbData =
2946 (BYTE *)pInfo->Algorithm.pszObjId
2947 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
2948 pInfo->PublicKey.cbData = encodedLen;
2949 pInfo->PublicKey.cUnusedBits = 0;
2950 ret = CryptEncodeObject(dwCertEncodingType,
2951 RSA_CSP_PUBLICKEYBLOB, pubKey,
2952 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
2956 CryptMemFree(pubKey);
2961 CryptDestroyKey(key);
2966 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
2967 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
2968 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
2970 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
2971 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
2972 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
2974 static HCRYPTOIDFUNCSET set = NULL;
2976 ExportPublicKeyInfoExFunc exportFunc = NULL;
2977 HCRYPTOIDFUNCADDR hFunc = NULL;
2979 TRACE("(%ld, %ld, %08lx, %s, %08lx, %p, %p, %p)\n", hCryptProv, dwKeySpec,
2980 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
2985 SetLastError(ERROR_INVALID_PARAMETER);
2989 if (pszPublicKeyObjId)
2992 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
2994 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
2995 0, (void **)&exportFunc, &hFunc);
2998 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
2999 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3000 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3002 CryptFreeOIDFunctionAddress(hFunc, 0);
3006 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3007 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3009 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3013 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3014 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3015 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3018 DWORD pubKeySize = 0;
3020 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
3021 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3023 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3024 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3027 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3031 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3032 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3035 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3037 CryptMemFree(pubKey);
3045 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3046 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3047 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3049 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3050 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3051 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3053 static HCRYPTOIDFUNCSET set = NULL;
3055 ImportPublicKeyInfoExFunc importFunc = NULL;
3056 HCRYPTOIDFUNCADDR hFunc = NULL;
3058 TRACE("(%ld, %ld, %p, %d, %08lx, %p, %p)\n", hCryptProv,
3059 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3062 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3063 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3064 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3066 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3067 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3070 CryptFreeOIDFunctionAddress(hFunc, 0);