2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER encoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "wine/unicode.h"
48 #include "crypt32_private.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
52 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
54 typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
55 DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
57 /* Prototypes for built-in encoders. They follow the Ex style prototypes.
58 * The dwCertEncodingType and lpszStructType are ignored by the built-in
59 * functions, but the parameters are retained to simplify CryptEncodeObjectEx,
60 * since it must call functions in external DLLs that follow these signatures.
62 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
63 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
64 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
65 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
66 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
67 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
68 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
69 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
70 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
71 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
72 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
73 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
74 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
76 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
77 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
79 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
80 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
81 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
82 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
83 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
84 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
85 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
86 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
87 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
88 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
89 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
91 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
92 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
94 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
95 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
96 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
97 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
99 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
100 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
102 static HCRYPTOIDFUNCSET set = NULL;
104 HCRYPTOIDFUNCADDR hFunc;
105 CryptEncodeObjectFunc pCryptEncodeObject;
107 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
108 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
111 if (!pbEncoded && !pcbEncoded)
113 SetLastError(ERROR_INVALID_PARAMETER);
117 /* Try registered DLL first.. */
119 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
120 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
121 (void **)&pCryptEncodeObject, &hFunc);
122 if (pCryptEncodeObject)
124 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
125 pvStructInfo, pbEncoded, pcbEncoded);
126 CryptFreeOIDFunctionAddress(hFunc, 0);
130 /* If not, use CryptEncodeObjectEx */
131 ret = CryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
132 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
137 /* Helper function to check *pcbEncoded, set it to the required size, and
138 * optionally to allocate memory. Assumes pbEncoded is not NULL.
139 * If CRYPT_ENCODE_ALLOC_FLAG is set in dwFlags, *pbEncoded will be set to a
140 * pointer to the newly allocated memory.
142 static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
143 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded,
148 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
150 if (pEncodePara && pEncodePara->pfnAlloc)
151 *(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
153 *(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
154 if (!*(BYTE **)pbEncoded)
157 *pcbEncoded = bytesNeeded;
159 else if (bytesNeeded > *pcbEncoded)
161 *pcbEncoded = bytesNeeded;
162 SetLastError(ERROR_MORE_DATA);
166 *pcbEncoded = bytesNeeded;
170 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
172 DWORD bytesNeeded, significantBytes = 0;
180 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
181 temp <<= 8, significantBytes--)
183 bytesNeeded = significantBytes + 1;
187 *pcbEncoded = bytesNeeded;
190 if (*pcbEncoded < bytesNeeded)
192 SetLastError(ERROR_MORE_DATA);
196 *pbEncoded = (BYTE)len;
201 *pbEncoded++ = significantBytes | 0x80;
202 for (i = 0; i < significantBytes; i++)
204 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
208 *pcbEncoded = bytesNeeded;
212 struct AsnEncodeSequenceItem
214 const void *pvStructInfo;
215 CryptEncodeObjectExFunc encodeFunc;
216 DWORD size; /* used during encoding, not for your use */
219 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
220 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
221 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
224 DWORD i, dataLen = 0;
226 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
227 pbEncoded, *pcbEncoded);
228 for (i = 0, ret = TRUE; ret && i < cItem; i++)
230 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
231 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
232 NULL, &items[i].size);
233 /* Some functions propagate their errors through the size */
235 *pcbEncoded = items[i].size;
236 dataLen += items[i].size;
240 DWORD lenBytes, bytesNeeded;
242 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
243 bytesNeeded = 1 + lenBytes + dataLen;
245 *pcbEncoded = bytesNeeded;
248 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
249 pcbEncoded, bytesNeeded)))
251 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
252 pbEncoded = *(BYTE **)pbEncoded;
253 *pbEncoded++ = ASN_SEQUENCE;
254 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
255 pbEncoded += lenBytes;
256 for (i = 0; ret && i < cItem; i++)
258 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
259 items[i].pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
260 NULL, pbEncoded, &items[i].size);
261 /* Some functions propagate their errors through the size */
263 *pcbEncoded = items[i].size;
264 pbEncoded += items[i].size;
269 TRACE("returning %d (%08x)\n", ret, GetLastError());
273 struct AsnConstructedItem
276 const void *pvStructInfo;
277 CryptEncodeObjectExFunc encodeFunc;
280 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
281 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
282 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
285 const struct AsnConstructedItem *item =
286 (const struct AsnConstructedItem *)pvStructInfo;
289 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
290 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
292 DWORD dataLen, bytesNeeded;
294 CRYPT_EncodeLen(len, NULL, &dataLen);
295 bytesNeeded = 1 + dataLen + len;
297 *pcbEncoded = bytesNeeded;
298 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
299 pbEncoded, pcbEncoded, bytesNeeded)))
301 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
302 pbEncoded = *(BYTE **)pbEncoded;
303 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
304 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
305 pbEncoded += dataLen;
306 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
307 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
311 /* Some functions propagate their errors through the size */
318 /* Some functions propagate their errors through the size */
324 struct AsnEncodeTagSwappedItem
327 const void *pvStructInfo;
328 CryptEncodeObjectExFunc encodeFunc;
331 /* Sort of a wacky hack, it encodes something using the struct
332 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
333 * given in the struct AsnEncodeTagSwappedItem.
335 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
336 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
337 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
340 const struct AsnEncodeTagSwappedItem *item =
341 (const struct AsnEncodeTagSwappedItem *)pvStructInfo;
343 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
344 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
345 if (ret && pbEncoded)
346 *pbEncoded = item->tag;
350 static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType,
351 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
352 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
354 const DWORD *ver = (const DWORD *)pvStructInfo;
357 /* CERT_V1 is not encoded */
365 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
367 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
368 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
373 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
374 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
375 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
377 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
382 *pcbEncoded = blob->cbData;
387 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
388 pcbEncoded, blob->cbData)))
390 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
391 pbEncoded = *(BYTE **)pbEncoded;
393 memcpy(pbEncoded, blob->pbData, blob->cbData);
394 *pcbEncoded = blob->cbData;
401 static BOOL WINAPI CRYPT_AsnEncodeValidity(DWORD dwCertEncodingType,
402 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
403 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
406 /* This has two filetimes in a row, a NotBefore and a NotAfter */
407 const FILETIME *timePtr = (const FILETIME *)pvStructInfo;
408 struct AsnEncodeSequenceItem items[] = {
409 { timePtr++, CRYPT_AsnEncodeChoiceOfTime, 0 },
410 { timePtr, CRYPT_AsnEncodeChoiceOfTime, 0 },
413 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
414 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
419 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmId(
420 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
421 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
424 const CRYPT_ALGORITHM_IDENTIFIER *algo =
425 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
427 struct AsnEncodeSequenceItem items[] = {
428 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
429 { &algo->Parameters, CRYPT_CopyEncodedBlob, 0 },
432 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
433 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
438 static BOOL WINAPI CRYPT_AsnEncodePubKeyInfo(DWORD dwCertEncodingType,
439 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
440 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
446 const CERT_PUBLIC_KEY_INFO *info =
447 (const CERT_PUBLIC_KEY_INFO *)pvStructInfo;
448 struct AsnEncodeSequenceItem items[] = {
449 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
450 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
453 TRACE("Encoding public key with OID %s\n",
454 debugstr_a(info->Algorithm.pszObjId));
455 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
456 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
461 SetLastError(STATUS_ACCESS_VIOLATION);
468 static BOOL WINAPI CRYPT_AsnEncodeCert(DWORD dwCertEncodingType,
469 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
470 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
476 const CERT_SIGNED_CONTENT_INFO *info =
477 (const CERT_SIGNED_CONTENT_INFO *)pvStructInfo;
478 struct AsnEncodeSequenceItem items[] = {
479 { &info->ToBeSigned, CRYPT_CopyEncodedBlob, 0 },
480 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
481 { &info->Signature, CRYPT_AsnEncodeBitsSwapBytes, 0 },
484 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
485 items[2].encodeFunc = CRYPT_AsnEncodeBits;
486 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
487 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
492 SetLastError(STATUS_ACCESS_VIOLATION);
499 /* Like in Windows, this blithely ignores the validity of the passed-in
500 * CERT_INFO, and just encodes it as-is. The resulting encoded data may not
501 * decode properly, see CRYPT_AsnDecodeCertInfo.
503 static BOOL WINAPI CRYPT_AsnEncodeCertInfo(DWORD dwCertEncodingType,
504 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
505 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
511 const CERT_INFO *info = (const CERT_INFO *)pvStructInfo;
512 struct AsnEncodeSequenceItem items[10] = {
513 { &info->dwVersion, CRYPT_AsnEncodeCertVersion, 0 },
514 { &info->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
515 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
516 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
517 { &info->NotBefore, CRYPT_AsnEncodeValidity, 0 },
518 { &info->Subject, CRYPT_CopyEncodedBlob, 0 },
519 { &info->SubjectPublicKeyInfo, CRYPT_AsnEncodePubKeyInfo, 0 },
522 struct AsnConstructedItem constructed[3] = { { 0 } };
523 DWORD cItem = 7, cConstructed = 0;
525 if (info->IssuerUniqueId.cbData)
527 constructed[cConstructed].tag = 1;
528 constructed[cConstructed].pvStructInfo = &info->IssuerUniqueId;
529 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
530 items[cItem].pvStructInfo = &constructed[cConstructed];
531 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
535 if (info->SubjectUniqueId.cbData)
537 constructed[cConstructed].tag = 2;
538 constructed[cConstructed].pvStructInfo = &info->SubjectUniqueId;
539 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeBits;
540 items[cItem].pvStructInfo = &constructed[cConstructed];
541 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
545 if (info->cExtension)
547 constructed[cConstructed].tag = 3;
548 constructed[cConstructed].pvStructInfo = &info->cExtension;
549 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
550 items[cItem].pvStructInfo = &constructed[cConstructed];
551 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
556 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
557 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
561 SetLastError(STATUS_ACCESS_VIOLATION);
568 static BOOL WINAPI CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
569 BYTE *pbEncoded, DWORD *pcbEncoded)
571 struct AsnEncodeSequenceItem items[3] = {
572 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
573 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
579 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
581 if (entry->cExtension)
583 items[cItem].pvStructInfo = &entry->cExtension;
584 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
588 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
589 pbEncoded, pcbEncoded);
591 TRACE("returning %d (%08x)\n", ret, GetLastError());
595 static BOOL WINAPI CRYPT_AsnEncodeCRLEntries(DWORD dwCertEncodingType,
596 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
597 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
599 DWORD cCRLEntry = *(const DWORD *)pvStructInfo;
600 DWORD bytesNeeded, dataLen, lenBytes, i;
601 const CRL_ENTRY *rgCRLEntry = *(const CRL_ENTRY *const *)
602 ((const BYTE *)pvStructInfo + sizeof(DWORD));
605 for (i = 0, dataLen = 0; ret && i < cCRLEntry; i++)
609 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
613 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
614 bytesNeeded = 1 + lenBytes + dataLen;
616 *pcbEncoded = bytesNeeded;
619 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
620 pcbEncoded, bytesNeeded)))
622 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
623 pbEncoded = *(BYTE **)pbEncoded;
624 *pbEncoded++ = ASN_SEQUENCEOF;
625 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
626 pbEncoded += lenBytes;
627 for (i = 0; i < cCRLEntry; i++)
629 DWORD size = dataLen;
631 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], pbEncoded, &size);
640 static BOOL WINAPI CRYPT_AsnEncodeCRLVersion(DWORD dwCertEncodingType,
641 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
642 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
644 const DWORD *ver = (const DWORD *)pvStructInfo;
647 /* CRL_V1 is not encoded */
654 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
655 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
659 /* Like in Windows, this blithely ignores the validity of the passed-in
660 * CRL_INFO, and just encodes it as-is. The resulting encoded data may not
661 * decode properly, see CRYPT_AsnDecodeCRLInfo.
663 static BOOL WINAPI CRYPT_AsnEncodeCRLInfo(DWORD dwCertEncodingType,
664 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
665 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
671 const CRL_INFO *info = (const CRL_INFO *)pvStructInfo;
672 struct AsnEncodeSequenceItem items[7] = {
673 { &info->dwVersion, CRYPT_AsnEncodeCRLVersion, 0 },
674 { &info->SignatureAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
675 { &info->Issuer, CRYPT_CopyEncodedBlob, 0 },
676 { &info->ThisUpdate, CRYPT_AsnEncodeChoiceOfTime, 0 },
679 struct AsnConstructedItem constructed[1] = { { 0 } };
680 DWORD cItem = 4, cConstructed = 0;
682 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
684 items[cItem].pvStructInfo = &info->NextUpdate;
685 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
690 items[cItem].pvStructInfo = &info->cCRLEntry;
691 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
694 if (info->cExtension)
696 constructed[cConstructed].tag = 0;
697 constructed[cConstructed].pvStructInfo = &info->cExtension;
698 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeExtensions;
699 items[cItem].pvStructInfo = &constructed[cConstructed];
700 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
705 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
706 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
710 SetLastError(STATUS_ACCESS_VIOLATION);
717 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
721 struct AsnEncodeSequenceItem items[3] = {
722 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
728 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
732 items[cItem].pvStructInfo = &ext->fCritical;
733 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
736 items[cItem].pvStructInfo = &ext->Value;
737 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
740 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
741 pbEncoded, pcbEncoded);
742 TRACE("returning %d (%08x)\n", ret, GetLastError());
746 static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
747 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
748 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
754 DWORD bytesNeeded, dataLen, lenBytes, i;
755 const CERT_EXTENSIONS *exts = (const CERT_EXTENSIONS *)pvStructInfo;
758 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
762 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
766 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
767 bytesNeeded = 1 + lenBytes + dataLen;
769 *pcbEncoded = bytesNeeded;
772 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
773 pcbEncoded, bytesNeeded)))
775 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
776 pbEncoded = *(BYTE **)pbEncoded;
777 *pbEncoded++ = ASN_SEQUENCEOF;
778 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
779 pbEncoded += lenBytes;
780 for (i = 0; i < exts->cExtension; i++)
782 DWORD size = dataLen;
784 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
794 SetLastError(STATUS_ACCESS_VIOLATION);
801 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
802 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
803 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
805 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
806 DWORD bytesNeeded = 0, lenBytes;
811 TRACE("%s\n", debugstr_a(pszObjId));
818 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
820 SetLastError(CRYPT_E_ASN1_ERROR);
824 firstByte = val1 * 40 + val2;
825 ptr = pszObjId + firstPos;
830 /* note I assume each component is at most 32-bits long in base 2 */
831 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
833 if (val1 >= 0x10000000)
835 else if (val1 >= 0x200000)
837 else if (val1 >= 0x4000)
839 else if (val1 >= 0x80)
849 SetLastError(CRYPT_E_ASN1_ERROR);
853 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
857 bytesNeeded += 1 + lenBytes;
860 if (*pcbEncoded < bytesNeeded)
862 SetLastError(ERROR_MORE_DATA);
867 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
868 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
869 pbEncoded += lenBytes;
875 *pbEncoded++ = firstByte;
876 ptr = pszObjId + firstPos;
879 sscanf(ptr, "%d%n", &val, &pos);
881 unsigned char outBytes[5];
884 if (val >= 0x10000000)
886 else if (val >= 0x200000)
888 else if (val >= 0x4000)
890 else if (val >= 0x80)
894 for (i = numBytes; i > 0; i--)
896 outBytes[i - 1] = val & 0x7f;
899 for (i = 0; i < numBytes - 1; i++)
900 *pbEncoded++ = outBytes[i] | 0x80;
901 *pbEncoded++ = outBytes[i];
910 *pcbEncoded = bytesNeeded;
914 static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
915 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
919 LPCSTR str = (LPCSTR)value->Value.pbData;
920 DWORD bytesNeeded, lenBytes, encodedLen;
922 encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
923 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
924 bytesNeeded = 1 + lenBytes + encodedLen;
926 *pcbEncoded = bytesNeeded;
929 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
930 pbEncoded, pcbEncoded, bytesNeeded)))
932 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
933 pbEncoded = *(BYTE **)pbEncoded;
935 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
936 pbEncoded += lenBytes;
937 memcpy(pbEncoded, str, encodedLen);
943 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
944 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
948 LPCWSTR str = (LPCWSTR)value->Value.pbData;
949 DWORD bytesNeeded, lenBytes, strLen;
951 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
953 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
954 bytesNeeded = 1 + lenBytes + strLen * 2;
956 *pcbEncoded = bytesNeeded;
959 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
960 pbEncoded, pcbEncoded, bytesNeeded)))
964 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
965 pbEncoded = *(BYTE **)pbEncoded;
966 *pbEncoded++ = ASN_BMPSTRING;
967 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
968 pbEncoded += lenBytes;
969 for (i = 0; i < strLen; i++)
971 *pbEncoded++ = (str[i] & 0xff00) >> 8;
972 *pbEncoded++ = str[i] & 0x00ff;
979 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
980 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
984 LPCWSTR str = (LPCWSTR)value->Value.pbData;
985 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
987 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
989 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
991 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
992 bytesNeeded = 1 + lenBytes + encodedLen;
994 *pcbEncoded = bytesNeeded;
997 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
998 pbEncoded, pcbEncoded, bytesNeeded)))
1000 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1001 pbEncoded = *(BYTE **)pbEncoded;
1002 *pbEncoded++ = ASN_UTF8STRING;
1003 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1004 pbEncoded += lenBytes;
1005 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1006 bytesNeeded - lenBytes - 1, NULL, NULL);
1012 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1013 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1014 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1020 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1022 switch (value->dwValueType)
1024 case CERT_RDN_ANY_TYPE:
1025 /* explicitly disallowed */
1026 SetLastError(E_INVALIDARG);
1029 case CERT_RDN_ENCODED_BLOB:
1030 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1031 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1033 case CERT_RDN_OCTET_STRING:
1034 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1035 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1037 case CERT_RDN_NUMERIC_STRING:
1038 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1039 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1041 case CERT_RDN_PRINTABLE_STRING:
1042 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1043 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1045 case CERT_RDN_TELETEX_STRING:
1046 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1047 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1049 case CERT_RDN_VIDEOTEX_STRING:
1050 ret = CRYPT_AsnEncodeStringCoerce(value,
1051 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1053 case CERT_RDN_IA5_STRING:
1054 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1055 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1057 case CERT_RDN_GRAPHIC_STRING:
1058 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1059 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1061 case CERT_RDN_VISIBLE_STRING:
1062 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1063 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1065 case CERT_RDN_GENERAL_STRING:
1066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1067 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1069 case CERT_RDN_UNIVERSAL_STRING:
1070 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1071 SetLastError(CRYPT_E_ASN1_CHOICE);
1074 case CERT_RDN_BMP_STRING:
1075 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1076 pbEncoded, pcbEncoded);
1078 case CERT_RDN_UTF8_STRING:
1079 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1080 pbEncoded, pcbEncoded);
1083 SetLastError(CRYPT_E_ASN1_CHOICE);
1089 SetLastError(STATUS_ACCESS_VIOLATION);
1096 static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1097 CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1098 BYTE *pbEncoded, DWORD *pcbEncoded)
1100 DWORD bytesNeeded = 0, lenBytes, size;
1103 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1104 0, NULL, NULL, &size);
1107 bytesNeeded += size;
1108 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1109 * with dwValueType, so "cast" it to get its encoded size
1111 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1112 (CERT_NAME_VALUE *)&attr->dwValueType, 0, NULL, NULL, &size);
1115 bytesNeeded += size;
1116 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1117 bytesNeeded += 1 + lenBytes;
1120 if (*pcbEncoded < bytesNeeded)
1122 SetLastError(ERROR_MORE_DATA);
1127 *pbEncoded++ = ASN_SEQUENCE;
1128 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1130 pbEncoded += lenBytes;
1131 size = bytesNeeded - 1 - lenBytes;
1132 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1133 attr->pszObjId, 0, NULL, pbEncoded, &size);
1137 size = bytesNeeded - 1 - lenBytes - size;
1138 ret = nameValueEncodeFunc(dwCertEncodingType,
1139 NULL, (CERT_NAME_VALUE *)&attr->dwValueType,
1140 0, NULL, pbEncoded, &size);
1147 *pcbEncoded = bytesNeeded;
1151 /* Have to propagate index of failing character */
1158 static int BLOBComp(const void *l, const void *r)
1160 const CRYPT_DER_BLOB *a = (const CRYPT_DER_BLOB *)l, *b = (const CRYPT_DER_BLOB *)r;
1163 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1164 ret = a->cbData - b->cbData;
1168 typedef struct _CRYPT_SET_OF {
1170 PCRYPT_DER_BLOB rgValue;
1173 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1175 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1176 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1177 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1179 const CRYPT_SET_OF *set = (const CRYPT_SET_OF *)pvStructInfo;
1180 DWORD bytesNeeded = 0, lenBytes, i;
1183 for (i = 0; i < set->cValue; i++)
1184 bytesNeeded += set->rgValue[i].cbData;
1185 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1186 bytesNeeded += 1 + lenBytes;
1189 *pcbEncoded = bytesNeeded;
1192 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1193 pbEncoded, pcbEncoded, bytesNeeded)))
1195 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1196 pbEncoded = *(BYTE **)pbEncoded;
1197 qsort(set->rgValue, set->cValue, sizeof(CRYPT_DER_BLOB), BLOBComp);
1198 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1199 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1200 pbEncoded += lenBytes;
1201 for (i = 0; ret && i < set->cValue; i++)
1203 memcpy(pbEncoded, set->rgValue[i].pbData, set->rgValue[i].cbData);
1204 pbEncoded += set->rgValue[i].cbData;
1210 static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
1211 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1215 CRYPT_SET_OF setOf = { 0, NULL };
1224 setOf.cValue = rdn->cRDNAttr;
1225 setOf.rgValue = CryptMemAlloc(rdn->cRDNAttr *
1226 sizeof(CRYPT_DER_BLOB));
1230 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1232 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1234 setOf.rgValue[i].cbData = 0;
1235 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1236 nameValueEncodeFunc, NULL, &setOf.rgValue[i].cbData);
1239 setOf.rgValue[i].pbData =
1240 CryptMemAlloc(setOf.rgValue[i].cbData);
1241 if (!setOf.rgValue[i].pbData)
1244 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1245 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1246 setOf.rgValue[i].pbData, &setOf.rgValue[i].cbData);
1250 /* Have to propagate index of failing character */
1251 *pcbEncoded = setOf.rgValue[i].cbData;
1255 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1256 pbEncoded, pcbEncoded);
1257 for (i = 0; i < setOf.cValue; i++)
1258 CryptMemFree(setOf.rgValue[i].pbData);
1262 SetLastError(STATUS_ACCESS_VIOLATION);
1266 CryptMemFree(setOf.rgValue);
1270 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1271 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1272 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1274 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1275 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1276 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1279 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1282 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1283 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1284 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1286 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1287 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1291 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1292 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1293 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1299 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1300 DWORD bytesNeeded = 0, lenBytes, size, i;
1302 TRACE("encoding name with %d RDNs\n", info->cRDN);
1304 for (i = 0; ret && i < info->cRDN; i++)
1306 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1307 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1309 bytesNeeded += size;
1313 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1314 bytesNeeded += 1 + lenBytes;
1318 *pcbEncoded = bytesNeeded;
1321 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1322 pbEncoded, pcbEncoded, bytesNeeded)))
1324 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1325 pbEncoded = *(BYTE **)pbEncoded;
1326 *pbEncoded++ = ASN_SEQUENCEOF;
1327 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1329 pbEncoded += lenBytes;
1330 for (i = 0; ret && i < info->cRDN; i++)
1333 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1334 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1339 bytesNeeded -= size;
1350 SetLastError(STATUS_ACCESS_VIOLATION);
1357 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1358 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1359 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1365 const CRYPT_ATTRIBUTE *attr = (const CRYPT_ATTRIBUTE *)pvStructInfo;
1367 if (!attr->pszObjId)
1368 SetLastError(E_INVALIDARG);
1371 struct AsnEncodeSequenceItem items[2] = {
1372 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1373 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1376 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1377 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1383 SetLastError(STATUS_ACCESS_VIOLATION);
1389 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1390 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1391 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1394 CRYPT_SET_OF setOf = { 0, NULL };
1399 const CRYPT_ATTRIBUTES *attributes =
1400 (const CRYPT_ATTRIBUTES *)pvStructInfo;
1403 if (attributes->cAttr)
1405 setOf.cValue = attributes->cAttr;
1406 setOf.rgValue = CryptMemAlloc(attributes->cAttr *
1407 sizeof(CRYPT_DER_BLOB));
1411 memset(setOf.rgValue, 0, setOf.cValue * sizeof(CRYPT_DER_BLOB));
1413 for (i = 0; ret && i < attributes->cAttr; i++)
1415 ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
1416 &attributes->rgAttr[i], 0, NULL, NULL, &setOf.rgValue[i].cbData);
1419 setOf.rgValue[i].pbData =
1420 CryptMemAlloc(setOf.rgValue[i].cbData);
1421 if (!setOf.rgValue[i].pbData)
1425 ret = CRYPT_AsnEncodePKCSAttribute(dwCertEncodingType, NULL,
1426 &attributes->rgAttr[i], 0, NULL, setOf.rgValue[i].pbData,
1427 &setOf.rgValue[i].cbData);
1432 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, dwFlags,
1433 pEncodePara, pbEncoded, pcbEncoded);
1434 for (i = 0; i < setOf.cValue; i++)
1435 CryptMemFree(setOf.rgValue[i].pbData);
1439 SetLastError(STATUS_ACCESS_VIOLATION);
1442 CryptMemFree(setOf.rgValue);
1446 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1447 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1448 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1454 const CRYPT_CONTENT_INFO *info =
1455 (const CRYPT_CONTENT_INFO *)pvStructInfo;
1457 if (!info->pszObjId)
1458 SetLastError(E_INVALIDARG);
1461 struct AsnEncodeSequenceItem items[2] = {
1462 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1465 struct AsnConstructedItem constructed = { 0 };
1468 if (info->Content.cbData)
1470 constructed.tag = 0;
1471 constructed.pvStructInfo = &info->Content;
1472 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1473 items[cItem].pvStructInfo = &constructed;
1474 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1477 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1478 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1484 SetLastError(STATUS_ACCESS_VIOLATION);
1490 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1491 BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1495 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1496 DWORD bytesNeeded, lenBytes, encodedLen;
1498 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1500 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1501 bytesNeeded = 1 + lenBytes + encodedLen;
1503 *pcbEncoded = bytesNeeded;
1506 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1507 pbEncoded, pcbEncoded, bytesNeeded)))
1511 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1512 pbEncoded = *(BYTE **)pbEncoded;
1514 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1515 pbEncoded += lenBytes;
1516 for (i = 0; i < encodedLen; i++)
1517 *pbEncoded++ = (BYTE)str[i];
1523 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
1524 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1528 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1529 DWORD bytesNeeded, lenBytes, encodedLen;
1531 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1533 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1534 bytesNeeded = 1 + lenBytes + encodedLen;
1536 *pcbEncoded = bytesNeeded;
1539 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1540 pbEncoded, pcbEncoded, bytesNeeded)))
1544 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1545 pbEncoded = *(BYTE **)pbEncoded;
1546 *pbEncoded++ = ASN_NUMERICSTRING;
1547 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1548 pbEncoded += lenBytes;
1549 for (i = 0; ret && i < encodedLen; i++)
1551 if (isdigitW(str[i]))
1552 *pbEncoded++ = (BYTE)str[i];
1556 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
1565 static inline int isprintableW(WCHAR wc)
1567 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
1568 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
1569 wc == '/' || wc == ':' || wc == '=' || wc == '?';
1572 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
1573 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1577 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1578 DWORD bytesNeeded, lenBytes, encodedLen;
1580 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1582 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1583 bytesNeeded = 1 + lenBytes + encodedLen;
1585 *pcbEncoded = bytesNeeded;
1588 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1589 pbEncoded, pcbEncoded, bytesNeeded)))
1593 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1594 pbEncoded = *(BYTE **)pbEncoded;
1595 *pbEncoded++ = ASN_PRINTABLESTRING;
1596 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1597 pbEncoded += lenBytes;
1598 for (i = 0; ret && i < encodedLen; i++)
1600 if (isprintableW(str[i]))
1601 *pbEncoded++ = (BYTE)str[i];
1605 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
1614 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
1615 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1619 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1620 DWORD bytesNeeded, lenBytes, encodedLen;
1622 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1624 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1625 bytesNeeded = 1 + lenBytes + encodedLen;
1627 *pcbEncoded = bytesNeeded;
1630 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1631 pbEncoded, pcbEncoded, bytesNeeded)))
1635 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1636 pbEncoded = *(BYTE **)pbEncoded;
1637 *pbEncoded++ = ASN_IA5STRING;
1638 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1639 pbEncoded += lenBytes;
1640 for (i = 0; ret && i < encodedLen; i++)
1643 *pbEncoded++ = (BYTE)str[i];
1647 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1656 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
1657 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1661 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1662 DWORD bytesNeeded, lenBytes, strLen;
1664 /* FIXME: doesn't handle composite characters */
1665 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1667 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
1668 bytesNeeded = 1 + lenBytes + strLen * 4;
1670 *pcbEncoded = bytesNeeded;
1673 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1674 pbEncoded, pcbEncoded, bytesNeeded)))
1678 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1679 pbEncoded = *(BYTE **)pbEncoded;
1680 *pbEncoded++ = ASN_UNIVERSALSTRING;
1681 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
1682 pbEncoded += lenBytes;
1683 for (i = 0; i < strLen; i++)
1687 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
1688 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
1695 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1696 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1697 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1703 const CERT_NAME_VALUE *value = (const CERT_NAME_VALUE *)pvStructInfo;
1705 switch (value->dwValueType)
1707 case CERT_RDN_ANY_TYPE:
1708 case CERT_RDN_ENCODED_BLOB:
1709 case CERT_RDN_OCTET_STRING:
1710 SetLastError(CRYPT_E_NOT_CHAR_STRING);
1712 case CERT_RDN_NUMERIC_STRING:
1713 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
1714 pbEncoded, pcbEncoded);
1716 case CERT_RDN_PRINTABLE_STRING:
1717 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
1718 pbEncoded, pcbEncoded);
1720 case CERT_RDN_TELETEX_STRING:
1721 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
1722 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1724 case CERT_RDN_VIDEOTEX_STRING:
1725 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
1726 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1728 case CERT_RDN_IA5_STRING:
1729 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
1730 pbEncoded, pcbEncoded);
1732 case CERT_RDN_GRAPHIC_STRING:
1733 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
1734 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1736 case CERT_RDN_VISIBLE_STRING:
1737 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
1738 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1740 case CERT_RDN_GENERAL_STRING:
1741 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
1742 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1744 case CERT_RDN_UNIVERSAL_STRING:
1745 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
1746 pbEncoded, pcbEncoded);
1748 case CERT_RDN_BMP_STRING:
1749 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1750 pbEncoded, pcbEncoded);
1752 case CERT_RDN_UTF8_STRING:
1753 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1754 pbEncoded, pcbEncoded);
1757 SetLastError(CRYPT_E_ASN1_CHOICE);
1762 SetLastError(STATUS_ACCESS_VIOLATION);
1768 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
1769 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1770 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1776 const CERT_NAME_INFO *info = (const CERT_NAME_INFO *)pvStructInfo;
1777 DWORD bytesNeeded = 0, lenBytes, size, i;
1779 TRACE("encoding name with %d RDNs\n", info->cRDN);
1781 for (i = 0; ret && i < info->cRDN; i++)
1783 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1784 CRYPT_AsnEncodeNameValue, NULL, &size);
1786 bytesNeeded += size;
1788 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1789 bytesNeeded += 1 + lenBytes;
1793 *pcbEncoded = bytesNeeded;
1796 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1797 pbEncoded, pcbEncoded, bytesNeeded)))
1799 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1800 pbEncoded = *(BYTE **)pbEncoded;
1801 *pbEncoded++ = ASN_SEQUENCEOF;
1802 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1804 pbEncoded += lenBytes;
1805 for (i = 0; ret && i < info->cRDN; i++)
1808 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1809 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, pbEncoded,
1814 bytesNeeded -= size;
1823 SetLastError(STATUS_ACCESS_VIOLATION);
1830 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1831 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1832 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1834 BOOL val = *(const BOOL *)pvStructInfo, ret;
1843 else if (*pcbEncoded < 3)
1846 SetLastError(ERROR_MORE_DATA);
1852 *pbEncoded++ = ASN_BOOL;
1854 *pbEncoded++ = val ? 0xff : 0;
1857 TRACE("returning %d (%08x)\n", ret, GetLastError());
1861 static BOOL CRYPT_AsnEncodeAltNameEntry(const CERT_ALT_NAME_ENTRY *entry,
1862 BYTE *pbEncoded, DWORD *pcbEncoded)
1868 switch (entry->dwAltNameChoice)
1870 case CERT_ALT_NAME_RFC822_NAME:
1871 case CERT_ALT_NAME_DNS_NAME:
1872 case CERT_ALT_NAME_URL:
1873 if (entry->u.pwszURL)
1877 /* Not + 1: don't encode the NULL-terminator */
1878 dataLen = lstrlenW(entry->u.pwszURL);
1879 for (i = 0; ret && i < dataLen; i++)
1881 if (entry->u.pwszURL[i] > 0x7f)
1883 SetLastError(CRYPT_E_INVALID_IA5_STRING);
1892 case CERT_ALT_NAME_IP_ADDRESS:
1893 dataLen = entry->u.IPAddress.cbData;
1895 case CERT_ALT_NAME_REGISTERED_ID:
1896 /* FIXME: encode OID */
1897 case CERT_ALT_NAME_OTHER_NAME:
1898 case CERT_ALT_NAME_DIRECTORY_NAME:
1899 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
1902 SetLastError(E_INVALIDARG);
1907 DWORD bytesNeeded, lenBytes;
1909 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1910 bytesNeeded = 1 + dataLen + lenBytes;
1912 *pcbEncoded = bytesNeeded;
1913 else if (*pcbEncoded < bytesNeeded)
1915 SetLastError(ERROR_MORE_DATA);
1916 *pcbEncoded = bytesNeeded;
1921 *pbEncoded++ = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
1922 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
1923 pbEncoded += lenBytes;
1924 switch (entry->dwAltNameChoice)
1926 case CERT_ALT_NAME_RFC822_NAME:
1927 case CERT_ALT_NAME_DNS_NAME:
1928 case CERT_ALT_NAME_URL:
1932 for (i = 0; i < dataLen; i++)
1933 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
1936 case CERT_ALT_NAME_IP_ADDRESS:
1937 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
1941 *pcbEncoded = bytesNeeded;
1944 TRACE("returning %d (%08x)\n", ret, GetLastError());
1948 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
1949 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1950 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1956 const CERT_AUTHORITY_KEY_ID_INFO *info =
1957 (const CERT_AUTHORITY_KEY_ID_INFO *)pvStructInfo;
1958 struct AsnEncodeSequenceItem items[3] = { { 0 } };
1959 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
1960 struct AsnConstructedItem constructed = { 0 };
1961 DWORD cItem = 0, cSwapped = 0;
1963 if (info->KeyId.cbData)
1965 swapped[cSwapped].tag = ASN_CONTEXT | 0;
1966 swapped[cSwapped].pvStructInfo = &info->KeyId;
1967 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1968 items[cItem].pvStructInfo = &swapped[cSwapped];
1969 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1973 if (info->CertIssuer.cbData)
1975 constructed.tag = 1;
1976 constructed.pvStructInfo = &info->CertIssuer;
1977 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1978 items[cItem].pvStructInfo = &constructed;
1979 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1982 if (info->CertSerialNumber.cbData)
1984 swapped[cSwapped].tag = ASN_CONTEXT | 2;
1985 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
1986 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
1987 items[cItem].pvStructInfo = &swapped[cSwapped];
1988 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
1992 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
1993 pEncodePara, pbEncoded, pcbEncoded);
1997 SetLastError(STATUS_ACCESS_VIOLATION);
2004 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2005 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2006 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2012 const CERT_ALT_NAME_INFO *info =
2013 (const CERT_ALT_NAME_INFO *)pvStructInfo;
2014 DWORD bytesNeeded, dataLen, lenBytes, i;
2017 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2018 * can't encode an erroneous entry index if it's bigger than this.
2020 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2024 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i], NULL,
2028 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2030 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2031 * the bad character, now set the index of the bad
2034 *pcbEncoded = (BYTE)i <<
2035 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2040 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2041 bytesNeeded = 1 + lenBytes + dataLen;
2044 *pcbEncoded = bytesNeeded;
2049 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2050 pbEncoded, pcbEncoded, bytesNeeded)))
2052 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2053 pbEncoded = *(BYTE **)pbEncoded;
2054 *pbEncoded++ = ASN_SEQUENCEOF;
2055 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2056 pbEncoded += lenBytes;
2057 for (i = 0; ret && i < info->cAltEntry; i++)
2059 DWORD len = dataLen;
2061 ret = CRYPT_AsnEncodeAltNameEntry(&info->rgAltEntry[i],
2075 SetLastError(STATUS_ACCESS_VIOLATION);
2082 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2083 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2084 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2090 const CERT_AUTHORITY_KEY_ID2_INFO *info =
2091 (const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
2092 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2093 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2094 DWORD cItem = 0, cSwapped = 0;
2096 if (info->KeyId.cbData)
2098 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2099 swapped[cSwapped].pvStructInfo = &info->KeyId;
2100 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2101 items[cItem].pvStructInfo = &swapped[cSwapped];
2102 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2106 if (info->AuthorityCertIssuer.cAltEntry)
2108 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2109 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2110 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2111 items[cItem].pvStructInfo = &swapped[cSwapped];
2112 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2116 if (info->AuthorityCertSerialNumber.cbData)
2118 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2119 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2120 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2121 items[cItem].pvStructInfo = &swapped[cSwapped];
2122 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2126 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2127 pEncodePara, pbEncoded, pcbEncoded);
2131 SetLastError(STATUS_ACCESS_VIOLATION);
2138 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2139 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2140 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2146 const CERT_BASIC_CONSTRAINTS_INFO *info =
2147 (const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
2148 struct AsnEncodeSequenceItem items[3] = {
2149 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2154 if (info->fPathLenConstraint)
2156 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2157 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2160 if (info->cSubtreesConstraint)
2162 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2163 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2166 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2167 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2171 SetLastError(STATUS_ACCESS_VIOLATION);
2178 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2179 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2180 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2186 const CERT_BASIC_CONSTRAINTS2_INFO *info =
2187 (const CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
2188 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2193 items[cItem].pvStructInfo = &info->fCA;
2194 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2197 if (info->fPathLenConstraint)
2199 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2200 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2203 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2204 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2208 SetLastError(STATUS_ACCESS_VIOLATION);
2215 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
2216 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2217 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2223 const BLOBHEADER *hdr =
2224 (const BLOBHEADER *)pvStructInfo;
2226 if (hdr->bType != PUBLICKEYBLOB)
2228 SetLastError(E_INVALIDARG);
2233 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
2234 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
2235 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
2236 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
2237 struct AsnEncodeSequenceItem items[] = {
2238 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
2239 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
2242 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2243 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
2249 SetLastError(STATUS_ACCESS_VIOLATION);
2256 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
2257 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2258 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2264 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
2265 DWORD bytesNeeded, lenBytes;
2267 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
2268 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
2270 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
2271 bytesNeeded = 1 + lenBytes + blob->cbData;
2274 *pcbEncoded = bytesNeeded;
2279 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2280 pcbEncoded, bytesNeeded)))
2282 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2283 pbEncoded = *(BYTE **)pbEncoded;
2284 *pbEncoded++ = ASN_OCTETSTRING;
2285 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
2286 pbEncoded += lenBytes;
2288 memcpy(pbEncoded, blob->pbData, blob->cbData);
2294 SetLastError(STATUS_ACCESS_VIOLATION);
2298 TRACE("returning %d (%08x)\n", ret, GetLastError());
2302 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
2303 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2304 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2310 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2311 DWORD bytesNeeded, lenBytes, dataBytes;
2314 /* yep, MS allows cUnusedBits to be >= 8 */
2315 if (!blob->cUnusedBits)
2317 dataBytes = blob->cbData;
2320 else if (blob->cbData * 8 > blob->cUnusedBits)
2322 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
2323 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
2331 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
2332 bytesNeeded = 1 + lenBytes + dataBytes + 1;
2335 *pcbEncoded = bytesNeeded;
2340 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2341 pcbEncoded, bytesNeeded)))
2343 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2344 pbEncoded = *(BYTE **)pbEncoded;
2345 *pbEncoded++ = ASN_BITSTRING;
2346 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
2347 pbEncoded += lenBytes;
2348 *pbEncoded++ = unusedBits;
2351 BYTE mask = 0xff << unusedBits;
2355 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
2356 pbEncoded += dataBytes - 1;
2358 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
2365 SetLastError(STATUS_ACCESS_VIOLATION);
2372 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
2373 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2374 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2380 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
2381 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
2386 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
2391 for (i = 0; i < newBlob.cbData; i++)
2392 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
2398 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
2399 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2400 CryptMemFree(newBlob.pbData);
2404 SetLastError(STATUS_ACCESS_VIOLATION);
2411 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
2412 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2413 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2415 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
2417 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
2418 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2421 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
2422 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2423 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2429 DWORD significantBytes, lenBytes;
2430 BYTE padByte = 0, bytesNeeded;
2432 const CRYPT_INTEGER_BLOB *blob =
2433 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2435 significantBytes = blob->cbData;
2436 if (significantBytes)
2438 if (blob->pbData[significantBytes - 1] & 0x80)
2440 /* negative, lop off leading (little-endian) 0xffs */
2441 for (; significantBytes > 0 &&
2442 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
2444 if (blob->pbData[significantBytes - 1] < 0x80)
2452 /* positive, lop off leading (little-endian) zeroes */
2453 for (; significantBytes > 0 &&
2454 !blob->pbData[significantBytes - 1]; significantBytes--)
2456 if (significantBytes == 0)
2457 significantBytes = 1;
2458 if (blob->pbData[significantBytes - 1] > 0x7f)
2466 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2468 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2469 bytesNeeded = 1 + lenBytes + significantBytes;
2474 *pcbEncoded = bytesNeeded;
2479 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2480 pcbEncoded, bytesNeeded)))
2482 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2483 pbEncoded = *(BYTE **)pbEncoded;
2484 *pbEncoded++ = ASN_INTEGER;
2487 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2488 pbEncoded += lenBytes;
2489 *pbEncoded++ = padByte;
2493 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2494 pbEncoded += lenBytes;
2496 for (; significantBytes > 0; significantBytes--)
2497 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2503 SetLastError(STATUS_ACCESS_VIOLATION);
2510 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
2511 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2512 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2518 DWORD significantBytes, lenBytes;
2521 const CRYPT_INTEGER_BLOB *blob =
2522 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
2524 significantBytes = blob->cbData;
2525 if (significantBytes)
2527 /* positive, lop off leading (little-endian) zeroes */
2528 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
2531 if (significantBytes == 0)
2532 significantBytes = 1;
2533 if (blob->pbData[significantBytes - 1] > 0x7f)
2537 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
2539 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
2540 bytesNeeded = 1 + lenBytes + significantBytes;
2545 *pcbEncoded = bytesNeeded;
2550 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2551 pcbEncoded, bytesNeeded)))
2553 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2554 pbEncoded = *(BYTE **)pbEncoded;
2555 *pbEncoded++ = ASN_INTEGER;
2558 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
2559 pbEncoded += lenBytes;
2564 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
2565 pbEncoded += lenBytes;
2567 for (; significantBytes > 0; significantBytes--)
2568 *(pbEncoded++) = blob->pbData[significantBytes - 1];
2574 SetLastError(STATUS_ACCESS_VIOLATION);
2581 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
2582 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2583 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2585 CRYPT_INTEGER_BLOB blob;
2588 /* Encode as an unsigned integer, then change the tag to enumerated */
2589 blob.cbData = sizeof(DWORD);
2590 blob.pbData = (BYTE *)pvStructInfo;
2591 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
2592 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2593 if (ret && pbEncoded)
2595 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2596 pbEncoded = *(BYTE **)pbEncoded;
2597 pbEncoded[0] = ASN_ENUMERATED;
2602 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
2603 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2604 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2611 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
2612 * temporary buffer because the output buffer is not NULL-terminated.
2615 static const DWORD bytesNeeded = sizeof(buf) - 1;
2619 *pcbEncoded = bytesNeeded;
2624 /* Sanity check the year, this is a two-digit year format */
2625 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2627 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
2629 SetLastError(CRYPT_E_BAD_ENCODE);
2634 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2635 pbEncoded, pcbEncoded, bytesNeeded)))
2637 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2638 pbEncoded = *(BYTE **)pbEncoded;
2639 buf[0] = ASN_UTCTIME;
2640 buf[1] = bytesNeeded - 2;
2641 snprintf(buf + 2, sizeof(buf) - 2,
2642 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
2643 sysTime.wYear - 2000 : sysTime.wYear - 1900,
2644 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2645 sysTime.wMinute, sysTime.wSecond);
2646 memcpy(pbEncoded, buf, bytesNeeded);
2653 SetLastError(STATUS_ACCESS_VIOLATION);
2660 static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
2661 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2662 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2669 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
2670 * temporary buffer because the output buffer is not NULL-terminated.
2673 static const DWORD bytesNeeded = sizeof(buf) - 1;
2677 *pcbEncoded = bytesNeeded;
2682 ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
2685 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2686 pcbEncoded, bytesNeeded);
2689 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2690 pbEncoded = *(BYTE **)pbEncoded;
2691 buf[0] = ASN_GENERALTIME;
2692 buf[1] = bytesNeeded - 2;
2693 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
2694 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
2695 sysTime.wMinute, sysTime.wSecond);
2696 memcpy(pbEncoded, buf, bytesNeeded);
2702 SetLastError(STATUS_ACCESS_VIOLATION);
2709 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
2710 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2711 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2719 /* Check the year, if it's in the UTCTime range call that encode func */
2720 if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
2722 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
2723 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
2724 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2726 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
2727 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
2732 SetLastError(STATUS_ACCESS_VIOLATION);
2739 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
2740 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2741 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2747 DWORD bytesNeeded, dataLen, lenBytes, i;
2748 const CRYPT_SEQUENCE_OF_ANY *seq =
2749 (const CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2751 for (i = 0, dataLen = 0; i < seq->cValue; i++)
2752 dataLen += seq->rgValue[i].cbData;
2753 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2754 bytesNeeded = 1 + lenBytes + dataLen;
2757 *pcbEncoded = bytesNeeded;
2762 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
2763 pcbEncoded, bytesNeeded)))
2765 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2766 pbEncoded = *(BYTE **)pbEncoded;
2767 *pbEncoded++ = ASN_SEQUENCEOF;
2768 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2769 pbEncoded += lenBytes;
2770 for (i = 0; i < seq->cValue; i++)
2772 memcpy(pbEncoded, seq->rgValue[i].pbData,
2773 seq->rgValue[i].cbData);
2774 pbEncoded += seq->rgValue[i].cbData;
2781 SetLastError(STATUS_ACCESS_VIOLATION);
2788 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
2789 BYTE *pbEncoded, DWORD *pcbEncoded)
2792 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2793 struct AsnConstructedItem constructed = { 0 };
2794 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2795 DWORD cItem = 0, cSwapped = 0;
2797 switch (distPoint->DistPointName.dwDistPointNameChoice)
2799 case CRL_DIST_POINT_NO_NAME:
2802 case CRL_DIST_POINT_FULL_NAME:
2803 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
2804 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
2805 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2806 constructed.tag = 0;
2807 constructed.pvStructInfo = &swapped[cSwapped];
2808 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
2809 items[cItem].pvStructInfo = &constructed;
2810 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2814 case CRL_DIST_POINT_ISSUER_RDN_NAME:
2815 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
2821 if (ret && distPoint->ReasonFlags.cbData)
2823 swapped[cSwapped].tag = ASN_CONTEXT | 1;
2824 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
2825 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
2826 items[cItem].pvStructInfo = &swapped[cSwapped];
2827 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2831 if (ret && distPoint->CRLIssuer.cAltEntry)
2833 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
2834 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
2835 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2836 items[cItem].pvStructInfo = &swapped[cSwapped];
2837 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2842 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
2843 pbEncoded, pcbEncoded);
2847 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
2848 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2849 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2855 const CRL_DIST_POINTS_INFO *info =
2856 (const CRL_DIST_POINTS_INFO *)pvStructInfo;
2858 if (!info->cDistPoint)
2860 SetLastError(E_INVALIDARG);
2865 DWORD bytesNeeded, dataLen, lenBytes, i;
2868 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
2872 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
2876 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2878 /* Have to propagate index of failing character */
2884 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2885 bytesNeeded = 1 + lenBytes + dataLen;
2888 *pcbEncoded = bytesNeeded;
2893 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2894 pbEncoded, pcbEncoded, bytesNeeded)))
2896 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2897 pbEncoded = *(BYTE **)pbEncoded;
2898 *pbEncoded++ = ASN_SEQUENCEOF;
2899 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2900 pbEncoded += lenBytes;
2901 for (i = 0; ret && i < info->cDistPoint; i++)
2903 DWORD len = dataLen;
2905 ret = CRYPT_AsnEncodeDistPoint(
2906 &info->rgDistPoint[i], pbEncoded, &len);
2920 SetLastError(STATUS_ACCESS_VIOLATION);
2927 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2928 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2929 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2935 const CERT_ENHKEY_USAGE *usage =
2936 (const CERT_ENHKEY_USAGE *)pvStructInfo;
2937 DWORD bytesNeeded = 0, lenBytes, size, i;
2940 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2942 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2943 usage->rgpszUsageIdentifier[i],
2944 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2946 bytesNeeded += size;
2948 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2949 bytesNeeded += 1 + lenBytes;
2953 *pcbEncoded = bytesNeeded;
2956 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2957 pbEncoded, pcbEncoded, bytesNeeded)))
2959 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2960 pbEncoded = *(BYTE **)pbEncoded;
2961 *pbEncoded++ = ASN_SEQUENCEOF;
2962 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
2964 pbEncoded += lenBytes;
2965 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
2968 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
2969 usage->rgpszUsageIdentifier[i],
2970 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
2975 bytesNeeded -= size;
2984 SetLastError(STATUS_ACCESS_VIOLATION);
2991 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
2992 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2993 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2999 const CRL_ISSUING_DIST_POINT *point =
3000 (const CRL_ISSUING_DIST_POINT *)pvStructInfo;
3001 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3002 struct AsnConstructedItem constructed = { 0 };
3003 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3004 DWORD cItem = 0, cSwapped = 0;
3007 switch (point->DistPointName.dwDistPointNameChoice)
3009 case CRL_DIST_POINT_NO_NAME:
3012 case CRL_DIST_POINT_FULL_NAME:
3013 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3014 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3015 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3016 constructed.tag = 0;
3017 constructed.pvStructInfo = &swapped[cSwapped];
3018 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3019 items[cItem].pvStructInfo = &constructed;
3020 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3025 SetLastError(E_INVALIDARG);
3028 if (ret && point->fOnlyContainsUserCerts)
3030 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3031 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3032 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3033 items[cItem].pvStructInfo = &swapped[cSwapped];
3034 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3038 if (ret && point->fOnlyContainsCACerts)
3040 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3041 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3042 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3043 items[cItem].pvStructInfo = &swapped[cSwapped];
3044 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3048 if (ret && point->OnlySomeReasonFlags.cbData)
3050 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3051 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3052 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3053 items[cItem].pvStructInfo = &swapped[cSwapped];
3054 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3058 if (ret && point->fIndirectCRL)
3060 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3061 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3062 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3063 items[cItem].pvStructInfo = &swapped[cSwapped];
3064 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3069 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3070 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3074 SetLastError(STATUS_ACCESS_VIOLATION);
3081 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
3082 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3083 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3087 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3088 (const CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3089 struct AsnEncodeSequenceItem items[] = {
3090 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
3091 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
3094 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3095 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3100 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
3101 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3102 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3106 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
3108 SetLastError(E_INVALIDARG);
3114 const CMSG_SIGNER_INFO *info = (const CMSG_SIGNER_INFO *)pvStructInfo;
3116 if (!info->Issuer.cbData)
3117 SetLastError(E_INVALIDARG);
3120 struct AsnEncodeSequenceItem items[7] = {
3121 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
3122 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
3123 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
3124 { &info->HashEncryptionAlgorithm, CRYPT_AsnEncodeAlgorithmId, 0 },
3128 if (info->AuthAttrs.cAttr)
3130 items[cItem].pvStructInfo = &info->AuthAttrs;
3131 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3134 if (info->UnauthAttrs.cAttr)
3136 items[cItem].pvStructInfo = &info->UnauthAttrs;
3137 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3140 items[cItem].pvStructInfo = &info->EncryptedHash;
3141 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
3143 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3144 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3149 SetLastError(STATUS_ACCESS_VIOLATION);
3155 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3156 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
3157 void *pvEncoded, DWORD *pcbEncoded)
3159 static HCRYPTOIDFUNCSET set = NULL;
3161 CryptEncodeObjectExFunc encodeFunc = NULL;
3162 HCRYPTOIDFUNCADDR hFunc = NULL;
3164 TRACE("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
3165 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
3166 pvEncoded, pcbEncoded);
3168 if (!pvEncoded && !pcbEncoded)
3170 SetLastError(ERROR_INVALID_PARAMETER);
3173 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3174 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3176 SetLastError(ERROR_FILE_NOT_FOUND);
3180 SetLastError(NOERROR);
3181 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG && pvEncoded)
3182 *(BYTE **)pvEncoded = NULL;
3183 if (!HIWORD(lpszStructType))
3185 switch (LOWORD(lpszStructType))
3187 case (WORD)X509_CERT:
3188 encodeFunc = CRYPT_AsnEncodeCert;
3190 case (WORD)X509_CERT_TO_BE_SIGNED:
3191 encodeFunc = CRYPT_AsnEncodeCertInfo;
3193 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3194 encodeFunc = CRYPT_AsnEncodeCRLInfo;
3196 case (WORD)X509_EXTENSIONS:
3197 encodeFunc = CRYPT_AsnEncodeExtensions;
3199 case (WORD)X509_NAME_VALUE:
3200 encodeFunc = CRYPT_AsnEncodeNameValue;
3202 case (WORD)X509_NAME:
3203 encodeFunc = CRYPT_AsnEncodeName;
3205 case (WORD)X509_PUBLIC_KEY_INFO:
3206 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
3208 case (WORD)X509_AUTHORITY_KEY_ID:
3209 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3211 case (WORD)X509_ALTERNATE_NAME:
3212 encodeFunc = CRYPT_AsnEncodeAltName;
3214 case (WORD)X509_BASIC_CONSTRAINTS:
3215 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3217 case (WORD)X509_BASIC_CONSTRAINTS2:
3218 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3220 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3221 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
3223 case (WORD)X509_UNICODE_NAME:
3224 encodeFunc = CRYPT_AsnEncodeUnicodeName;
3226 case (WORD)PKCS_CONTENT_INFO:
3227 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
3229 case (WORD)PKCS_ATTRIBUTE:
3230 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
3232 case (WORD)X509_UNICODE_NAME_VALUE:
3233 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
3235 case (WORD)X509_OCTET_STRING:
3236 encodeFunc = CRYPT_AsnEncodeOctets;
3238 case (WORD)X509_BITS:
3239 case (WORD)X509_KEY_USAGE:
3240 encodeFunc = CRYPT_AsnEncodeBits;
3242 case (WORD)X509_INTEGER:
3243 encodeFunc = CRYPT_AsnEncodeInt;
3245 case (WORD)X509_MULTI_BYTE_INTEGER:
3246 encodeFunc = CRYPT_AsnEncodeInteger;
3248 case (WORD)X509_MULTI_BYTE_UINT:
3249 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
3251 case (WORD)X509_ENUMERATED:
3252 encodeFunc = CRYPT_AsnEncodeEnumerated;
3254 case (WORD)X509_CHOICE_OF_TIME:
3255 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
3257 case (WORD)X509_AUTHORITY_KEY_ID2:
3258 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3260 case (WORD)X509_SEQUENCE_OF_ANY:
3261 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
3263 case (WORD)PKCS_UTC_TIME:
3264 encodeFunc = CRYPT_AsnEncodeUtcTime;
3266 case (WORD)X509_CRL_DIST_POINTS:
3267 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3269 case (WORD)X509_ENHANCED_KEY_USAGE:
3270 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3272 case (WORD)PKCS_ATTRIBUTES:
3273 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
3275 case (WORD)X509_ISSUING_DIST_POINT:
3276 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3278 case (WORD)PKCS7_SIGNER_INFO:
3279 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
3282 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3285 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3286 encodeFunc = CRYPT_AsnEncodeExtensions;
3287 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3288 encodeFunc = CRYPT_AsnEncodeUtcTime;
3289 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3290 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
3291 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3292 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
3293 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3294 encodeFunc = CRYPT_AsnEncodeEnumerated;
3295 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3296 encodeFunc = CRYPT_AsnEncodeBits;
3297 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3298 encodeFunc = CRYPT_AsnEncodeOctets;
3299 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3300 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
3301 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3302 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
3303 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3304 encodeFunc = CRYPT_AsnEncodeAltName;
3305 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3306 encodeFunc = CRYPT_AsnEncodeAltName;
3307 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3308 encodeFunc = CRYPT_AsnEncodeAltName;
3309 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3310 encodeFunc = CRYPT_AsnEncodeAltName;
3311 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3312 encodeFunc = CRYPT_AsnEncodeAltName;
3313 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3314 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
3315 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3316 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
3317 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3318 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
3320 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3321 debugstr_a(lpszStructType));
3325 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
3326 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3327 (void **)&encodeFunc, &hFunc);
3330 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
3331 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
3333 SetLastError(ERROR_FILE_NOT_FOUND);
3335 CryptFreeOIDFunctionAddress(hFunc, 0);
3339 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3340 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3342 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
3343 NULL, 0, NULL, pInfo, pcbInfo);
3346 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3347 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3348 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3352 static CHAR oid[] = szOID_RSA_RSA;
3354 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3355 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3358 if (!pszPublicKeyObjId)
3359 pszPublicKeyObjId = oid;
3360 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
3364 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
3367 LPBYTE pubKey = CryptMemAlloc(keySize);
3371 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
3375 DWORD encodedLen = 0;
3377 ret = CryptEncodeObject(dwCertEncodingType,
3378 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
3381 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
3382 strlen(pszPublicKeyObjId) + 1 + encodedLen;
3385 *pcbInfo = sizeNeeded;
3386 else if (*pcbInfo < sizeNeeded)
3388 SetLastError(ERROR_MORE_DATA);
3389 *pcbInfo = sizeNeeded;
3394 pInfo->Algorithm.pszObjId = (char *)pInfo +
3395 sizeof(CERT_PUBLIC_KEY_INFO);
3396 lstrcpyA(pInfo->Algorithm.pszObjId,
3398 pInfo->Algorithm.Parameters.cbData = 0;
3399 pInfo->Algorithm.Parameters.pbData = NULL;
3400 pInfo->PublicKey.pbData =
3401 (BYTE *)pInfo->Algorithm.pszObjId
3402 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
3403 pInfo->PublicKey.cbData = encodedLen;
3404 pInfo->PublicKey.cUnusedBits = 0;
3405 ret = CryptEncodeObject(dwCertEncodingType,
3406 RSA_CSP_PUBLICKEYBLOB, pubKey,
3407 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
3411 CryptMemFree(pubKey);
3416 CryptDestroyKey(key);
3421 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3422 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
3423 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
3425 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec,
3426 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
3427 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
3429 static HCRYPTOIDFUNCSET set = NULL;
3431 ExportPublicKeyInfoExFunc exportFunc = NULL;
3432 HCRYPTOIDFUNCADDR hFunc = NULL;
3434 TRACE("(%08lx, %d, %08x, %s, %08x, %p, %p, %p)\n", hCryptProv, dwKeySpec,
3435 dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags, pvAuxInfo,
3440 SetLastError(ERROR_INVALID_PARAMETER);
3444 if (pszPublicKeyObjId)
3447 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
3449 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
3450 0, (void **)&exportFunc, &hFunc);
3453 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
3454 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
3455 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
3457 CryptFreeOIDFunctionAddress(hFunc, 0);
3461 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
3462 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
3464 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
3468 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3469 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3470 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3473 DWORD pubKeySize = 0;
3475 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3476 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3478 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3479 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
3482 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
3486 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
3487 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
3490 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
3492 CryptMemFree(pubKey);
3500 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
3501 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3502 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
3504 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
3505 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
3506 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
3508 static HCRYPTOIDFUNCSET set = NULL;
3510 ImportPublicKeyInfoExFunc importFunc = NULL;
3511 HCRYPTOIDFUNCADDR hFunc = NULL;
3513 TRACE("(%08lx, %d, %p, %d, %08x, %p, %p)\n", hCryptProv,
3514 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
3517 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
3518 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
3519 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
3521 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
3522 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
3525 CryptFreeOIDFunctionAddress(hFunc, 0);