1 /* wintrust asn functions
3 * Copyright 2007 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
36 #include "wine/exception.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
40 #ifdef WORDS_BIGENDIAN
47 #define hton16(x) RtlUshortByteSwap(x)
48 #define n16toh(x) RtlUshortByteSwap(x)
52 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
53 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
54 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
56 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
58 DWORD bytesNeeded, significantBytes = 0;
66 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
67 temp <<= 8, significantBytes--)
69 bytesNeeded = significantBytes + 1;
73 *pcbEncoded = bytesNeeded;
76 if (*pcbEncoded < bytesNeeded)
78 SetLastError(ERROR_MORE_DATA);
82 *pbEncoded = (BYTE)len;
87 *pbEncoded++ = significantBytes | 0x80;
88 for (i = 0; i < significantBytes; i++)
90 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
94 *pcbEncoded = bytesNeeded;
98 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
103 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
104 DWORD bytesNeeded, lenBytes;
106 TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
109 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
110 bytesNeeded = 1 + lenBytes + blob->cbData;
112 *pcbEncoded = bytesNeeded;
113 else if (*pcbEncoded < bytesNeeded)
115 *pcbEncoded = bytesNeeded;
116 SetLastError(ERROR_MORE_DATA);
121 *pbEncoded++ = ASN_OCTETSTRING;
122 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
123 pbEncoded += lenBytes;
125 memcpy(pbEncoded, blob->pbData, blob->cbData);
127 TRACE("returning %d\n", ret);
131 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
132 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
137 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
138 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
143 const SPC_LINK *link = (const SPC_LINK *)pvStructInfo;
144 DWORD bytesNeeded, lenBytes;
146 switch (link->dwLinkChoice)
148 case SPC_FILE_LINK_CHOICE:
150 DWORD fileNameLen, fileNameLenBytes;
153 fileNameLen = link->u.pwszFile ?
154 lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
155 CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
156 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
158 bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
161 *pcbEncoded = bytesNeeded;
164 else if (*pcbEncoded < bytesNeeded)
166 SetLastError(ERROR_MORE_DATA);
167 *pcbEncoded = bytesNeeded;
171 *pcbEncoded = bytesNeeded;
172 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
173 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
175 pbEncoded += lenBytes;
176 *pbEncoded++ = ASN_CONTEXT;
177 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
178 pbEncoded += fileNameLenBytes;
179 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
181 *(WCHAR *)pbEncoded = hton16(*ptr);
182 pbEncoded += sizeof(WCHAR);
188 case SPC_MONIKER_LINK_CHOICE:
190 DWORD classIdLenBytes, dataLenBytes, dataLen;
191 CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
192 (BYTE *)link->u.Moniker.ClassId };
194 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
195 CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
197 dataLen = 2 + classIdLenBytes + classId.cbData +
198 dataLenBytes + link->u.Moniker.SerializedData.cbData;
199 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
200 bytesNeeded = 1 + dataLen + lenBytes;
203 *pcbEncoded = bytesNeeded;
206 else if (*pcbEncoded < bytesNeeded)
208 SetLastError(ERROR_MORE_DATA);
209 *pcbEncoded = bytesNeeded;
215 *pcbEncoded = bytesNeeded;
216 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
217 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
218 pbEncoded += lenBytes;
219 size = 1 + classIdLenBytes + classId.cbData;
220 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
223 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
224 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
225 &link->u.Moniker.SerializedData, pbEncoded, &size);
231 case SPC_URL_LINK_CHOICE:
236 /* Check for invalid characters in URL */
239 for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
243 SetLastError(CRYPT_E_INVALID_IA5_STRING);
250 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
251 bytesNeeded = 1 + lenBytes + urlLen;
253 *pcbEncoded = bytesNeeded;
254 else if (*pcbEncoded < bytesNeeded)
256 SetLastError(ERROR_MORE_DATA);
257 *pcbEncoded = bytesNeeded;
262 *pcbEncoded = bytesNeeded;
263 *pbEncoded++ = ASN_CONTEXT;
264 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
265 pbEncoded += lenBytes;
266 for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
267 *pbEncoded++ = (BYTE)*ptr;
273 SetLastError(E_INVALIDARG);
278 SetLastError(STATUS_ACCESS_VIOLATION);
281 TRACE("returning %d\n", ret);
285 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
288 struct AsnEncodeSequenceItem
290 const void *pvStructInfo;
291 CryptEncodeObjectFunc encodeFunc;
292 DWORD size; /* used during encoding, not for your use */
295 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
296 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
300 DWORD i, dataLen = 0;
302 TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
303 for (i = 0, ret = TRUE; ret && i < cItem; i++)
305 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
306 items[i].pvStructInfo, NULL, &items[i].size);
307 /* Some functions propagate their errors through the size */
309 *pcbEncoded = items[i].size;
310 dataLen += items[i].size;
314 DWORD lenBytes, bytesNeeded;
316 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
317 bytesNeeded = 1 + lenBytes + dataLen;
319 *pcbEncoded = bytesNeeded;
320 else if (*pcbEncoded < bytesNeeded)
322 *pcbEncoded = bytesNeeded;
323 SetLastError(ERROR_MORE_DATA);
328 *pcbEncoded = bytesNeeded;
329 *pbEncoded++ = ASN_SEQUENCE;
330 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
331 pbEncoded += lenBytes;
332 for (i = 0; ret && i < cItem; i++)
334 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
335 items[i].pvStructInfo, pbEncoded, &items[i].size);
336 /* Some functions propagate their errors through the size */
338 *pcbEncoded = items[i].size;
339 pbEncoded += items[i].size;
343 TRACE("returning %d\n", ret);
347 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
348 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
355 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
356 DWORD bytesNeeded, lenBytes, dataBytes;
359 /* yep, MS allows cUnusedBits to be >= 8 */
360 if (!blob->cUnusedBits)
362 dataBytes = blob->cbData;
365 else if (blob->cbData * 8 > blob->cUnusedBits)
367 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
368 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
376 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
377 bytesNeeded = 1 + lenBytes + dataBytes + 1;
380 *pcbEncoded = bytesNeeded;
383 else if (*pcbEncoded < bytesNeeded)
385 *pcbEncoded = bytesNeeded;
386 SetLastError(ERROR_MORE_DATA);
391 *pcbEncoded = bytesNeeded;
392 *pbEncoded++ = ASN_BITSTRING;
393 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
394 pbEncoded += lenBytes;
395 *pbEncoded++ = unusedBits;
398 BYTE mask = 0xff << unusedBits;
402 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
403 pbEncoded += dataBytes - 1;
405 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
411 SetLastError(STATUS_ACCESS_VIOLATION);
417 struct AsnConstructedItem
420 const void *pvStructInfo;
421 CryptEncodeObjectFunc encodeFunc;
424 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
425 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
429 const struct AsnConstructedItem *item =
430 (const struct AsnConstructedItem *)pvStructInfo;
433 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
434 item->pvStructInfo, NULL, &len)))
436 DWORD dataLen, bytesNeeded;
438 CRYPT_EncodeLen(len, NULL, &dataLen);
439 bytesNeeded = 1 + dataLen + len;
441 *pcbEncoded = bytesNeeded;
442 else if (*pcbEncoded < bytesNeeded)
444 *pcbEncoded = bytesNeeded;
445 SetLastError(ERROR_MORE_DATA);
450 *pcbEncoded = bytesNeeded;
451 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
452 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
453 pbEncoded += dataLen;
454 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
455 item->pvStructInfo, pbEncoded, &len);
458 /* Some functions propagate their errors through the size */
465 /* Some functions propagate their errors through the size */
472 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
473 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
476 const SPC_PE_IMAGE_DATA *imageData =
477 (const SPC_PE_IMAGE_DATA *)pvStructInfo;
480 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
481 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
486 struct AsnEncodeSequenceItem items[2] = {
489 struct AsnConstructedItem constructed = { 0, imageData->pFile,
490 WVTAsn1SpcLinkEncode };
493 if (imageData->Flags.cbData)
495 items[cItem].pvStructInfo = &imageData->Flags;
496 items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
499 if (imageData->pFile)
501 items[cItem].pvStructInfo = &constructed;
502 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
506 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
507 pbEncoded, pcbEncoded);
511 SetLastError(STATUS_ACCESS_VIOLATION);
514 TRACE("returning %d\n", ret);
518 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
519 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
522 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
523 DWORD bytesNeeded = 0, lenBytes;
528 TRACE("%s\n", debugstr_a(pszObjId));
535 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
537 SetLastError(CRYPT_E_ASN1_ERROR);
541 firstByte = val1 * 40 + val2;
542 ptr = pszObjId + firstPos;
547 /* note I assume each component is at most 32-bits long in base 2 */
548 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
550 if (val1 >= 0x10000000)
552 else if (val1 >= 0x200000)
554 else if (val1 >= 0x4000)
556 else if (val1 >= 0x80)
566 SetLastError(CRYPT_E_ASN1_ERROR);
570 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
574 bytesNeeded += 1 + lenBytes;
577 if (*pcbEncoded < bytesNeeded)
579 SetLastError(ERROR_MORE_DATA);
584 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
585 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
586 pbEncoded += lenBytes;
592 *pbEncoded++ = firstByte;
593 ptr = pszObjId + firstPos;
596 sscanf(ptr, "%d%n", &val, &pos);
598 unsigned char outBytes[5];
601 if (val >= 0x10000000)
603 else if (val >= 0x200000)
605 else if (val >= 0x4000)
607 else if (val >= 0x80)
611 for (i = numBytes; i > 0; i--)
613 outBytes[i - 1] = val & 0x7f;
616 for (i = 0; i < numBytes - 1; i++)
617 *pbEncoded++ = outBytes[i] | 0x80;
618 *pbEncoded++ = outBytes[i];
627 *pcbEncoded = bytesNeeded;
631 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
632 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
635 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
639 *pcbEncoded = blob->cbData;
640 else if (*pcbEncoded < blob->cbData)
642 *pcbEncoded = blob->cbData;
643 SetLastError(ERROR_MORE_DATA);
649 memcpy(pbEncoded, blob->pbData, blob->cbData);
650 *pcbEncoded = blob->cbData;
655 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
656 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
657 BYTE *pbEncoded, DWORD *pcbEncoded)
659 const CRYPT_ALGORITHM_IDENTIFIER *algo =
660 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
661 static const BYTE asn1Null[] = { ASN_NULL, 0 };
662 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
665 struct AsnEncodeSequenceItem items[2] = {
666 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
667 { NULL, CRYPT_CopyEncodedBlob, 0 },
670 if (algo->Parameters.cbData)
671 items[1].pvStructInfo = &algo->Parameters;
673 items[1].pvStructInfo = &nullBlob;
674 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
675 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
679 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
680 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
683 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
684 (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
685 struct AsnEncodeSequenceItem items[] = {
686 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
687 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
690 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
691 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
696 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
697 CRYPT_HASH_BLOB Digest;
700 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
701 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
704 const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
705 struct AsnEncodeSequenceItem items[] = {
706 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
707 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 },
710 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
711 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
714 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
720 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
721 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
725 const SPC_INDIRECT_DATA_CONTENT *data =
726 (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
727 struct AsnEncodeSequenceItem items[] = {
728 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
729 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
732 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
733 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
737 SetLastError(STATUS_ACCESS_VIOLATION);
743 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
744 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
748 LPCWSTR str = (LPCWSTR)pvStructInfo;
749 DWORD bytesNeeded, lenBytes, strLen;
752 strLen = lstrlenW(str);
755 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
756 bytesNeeded = 1 + lenBytes + strLen * 2;
758 *pcbEncoded = bytesNeeded;
759 else if (*pcbEncoded < bytesNeeded)
761 *pcbEncoded = bytesNeeded;
762 SetLastError(ERROR_MORE_DATA);
769 *pcbEncoded = bytesNeeded;
770 *pbEncoded++ = ASN_BMPSTRING;
771 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
772 pbEncoded += lenBytes;
773 for (i = 0; i < strLen; i++)
775 *pbEncoded++ = (str[i] & 0xff00) >> 8;
776 *pbEncoded++ = str[i] & 0x00ff;
782 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
783 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
790 DWORD significantBytes, lenBytes, bytesNeeded;
793 const CRYPT_INTEGER_BLOB *blob =
794 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
796 significantBytes = blob->cbData;
797 if (significantBytes)
799 if (blob->pbData[significantBytes - 1] & 0x80)
801 /* negative, lop off leading (little-endian) 0xffs */
802 for (; significantBytes > 0 &&
803 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
805 if (blob->pbData[significantBytes - 1] < 0x80)
813 /* positive, lop off leading (little-endian) zeroes */
814 for (; significantBytes > 0 &&
815 !blob->pbData[significantBytes - 1]; significantBytes--)
817 if (significantBytes == 0)
818 significantBytes = 1;
819 if (blob->pbData[significantBytes - 1] > 0x7f)
827 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
829 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
830 bytesNeeded = 1 + lenBytes + significantBytes;
835 *pcbEncoded = bytesNeeded;
838 else if (*pcbEncoded < bytesNeeded)
840 *pcbEncoded = bytesNeeded;
841 SetLastError(ERROR_MORE_DATA);
846 *pcbEncoded = bytesNeeded;
847 *pbEncoded++ = ASN_INTEGER;
850 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
851 pbEncoded += lenBytes;
852 *pbEncoded++ = padByte;
856 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
857 pbEncoded += lenBytes;
859 for (; significantBytes > 0; significantBytes--)
860 *(pbEncoded++) = blob->pbData[significantBytes - 1];
866 SetLastError(STATUS_ACCESS_VIOLATION);
873 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
874 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
877 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
879 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
880 &blob, pbEncoded, pcbEncoded);
883 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
884 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
889 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
890 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
894 const CAT_MEMBERINFO *info = (const CAT_MEMBERINFO *)pvStructInfo;
895 struct AsnEncodeSequenceItem items[] = {
896 { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
897 { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
900 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
901 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
905 SetLastError(STATUS_ACCESS_VIOLATION);
911 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
912 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
917 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
918 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
922 const CAT_NAMEVALUE *value = (const CAT_NAMEVALUE *)pvStructInfo;
923 struct AsnEncodeSequenceItem items[] = {
924 { value->pwszTag, CRYPT_AsnEncodeBMPString, 0 },
925 { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
926 { &value->Value, CRYPT_AsnEncodeOctets, 0 },
929 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
930 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
934 SetLastError(STATUS_ACCESS_VIOLATION);
940 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
941 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
944 BOOL val = *(const BOOL *)pvStructInfo, ret;
953 else if (*pcbEncoded < 3)
956 SetLastError(ERROR_MORE_DATA);
962 *pbEncoded++ = ASN_BOOL;
964 *pbEncoded++ = val ? 0xff : 0;
967 TRACE("returning %d (%08x)\n", ret, GetLastError());
971 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType,
972 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
977 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
978 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
982 const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo;
983 struct AsnEncodeSequenceItem items[] = {
984 { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 },
985 { &criteria->fMeetsCriteria, CRYPT_AsnEncodeBool, 0 },
988 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
989 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
993 SetLastError(STATUS_ACCESS_VIOLATION);
999 /* Gets the number of length bytes from the given (leading) length byte */
1000 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1002 /* Helper function to get the encoded length of the data starting at pbEncoded,
1003 * where pbEncoded[0] is the tag. If the data are too short to contain a
1004 * length or if the length is too large for cbEncoded, sets an appropriate
1005 * error code and returns FALSE.
1007 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
1013 SetLastError(CRYPT_E_ASN1_CORRUPT);
1016 else if (pbEncoded[1] <= 0x7f)
1018 if (pbEncoded[1] + 1 > cbEncoded)
1020 SetLastError(CRYPT_E_ASN1_EOD);
1025 *len = pbEncoded[1];
1029 else if (pbEncoded[1] == 0x80)
1031 FIXME("unimplemented for indefinite-length encoding\n");
1032 SetLastError(CRYPT_E_ASN1_CORRUPT);
1037 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
1039 if (lenLen > sizeof(DWORD) + 1)
1041 SetLastError(CRYPT_E_ASN1_LARGE);
1044 else if (lenLen + 2 > cbEncoded)
1046 SetLastError(CRYPT_E_ASN1_CORRUPT);
1057 out |= *pbEncoded++;
1059 if (out + lenLen + 1 > cbEncoded)
1061 SetLastError(CRYPT_E_ASN1_EOD);
1074 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1075 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1076 void *pvStructInfo, DWORD *pcbStructInfo)
1079 DWORD bytesNeeded, dataLen;
1081 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1082 pvStructInfo, *pcbStructInfo);
1086 SetLastError(CRYPT_E_ASN1_CORRUPT);
1089 else if (pbEncoded[0] != ASN_OCTETSTRING)
1091 SetLastError(CRYPT_E_ASN1_BADTAG);
1094 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1096 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1097 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1099 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1101 *pcbStructInfo = bytesNeeded;
1102 else if (*pcbStructInfo < bytesNeeded)
1104 SetLastError(ERROR_MORE_DATA);
1105 *pcbStructInfo = bytesNeeded;
1110 CRYPT_DATA_BLOB *blob;
1111 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1113 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1114 blob->cbData = dataLen;
1115 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1116 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1119 assert(blob->pbData);
1121 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1129 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
1130 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1131 void *pvStructInfo, DWORD *pcbStructInfo)
1134 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
1136 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1137 pvStructInfo, *pcbStructInfo);
1139 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1141 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1144 switch (pbEncoded[0])
1147 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1149 *pcbStructInfo = bytesNeeded;
1150 else if (*pcbStructInfo < bytesNeeded)
1152 *pcbStructInfo = bytesNeeded;
1153 SetLastError(ERROR_MORE_DATA);
1158 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1161 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
1162 for (i = 0; i < dataLen; i++)
1163 link->u.pwszUrl[i] =
1164 *(pbEncoded + 1 + lenBytes + i);
1165 link->u.pwszUrl[i] = '\0';
1166 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
1169 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
1171 CRYPT_DATA_BLOB classId;
1172 DWORD size = sizeof(classId);
1174 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1175 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
1176 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
1178 if (classId.cbData != sizeof(SPC_UUID))
1180 SetLastError(CRYPT_E_BAD_ENCODE);
1185 CRYPT_DATA_BLOB data;
1187 /* The tag length for the classId must be 1 since the
1188 * length is correct.
1190 size = sizeof(data);
1191 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1192 pbEncoded + 3 + lenBytes + classId.cbData,
1193 cbEncoded - 3 - lenBytes - classId.cbData,
1194 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
1196 bytesNeeded += data.cbData;
1198 *pcbStructInfo = bytesNeeded;
1199 else if (*pcbStructInfo < bytesNeeded)
1201 *pcbStructInfo = bytesNeeded;
1202 SetLastError(ERROR_MORE_DATA);
1207 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1209 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
1210 /* pwszFile pointer was set by caller, copy it
1211 * before overwriting it
1213 link->u.Moniker.SerializedData.pbData =
1214 (BYTE *)link->u.pwszFile;
1215 memcpy(link->u.Moniker.ClassId, classId.pbData,
1217 memcpy(link->u.Moniker.SerializedData.pbData,
1218 data.pbData, data.cbData);
1219 link->u.Moniker.SerializedData.cbData = data.cbData;
1226 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
1227 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
1228 SetLastError(CRYPT_E_ASN1_BADTAG);
1229 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
1232 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
1234 bytesNeeded += realDataLen + sizeof(WCHAR);
1236 *pcbStructInfo = bytesNeeded;
1237 else if (*pcbStructInfo < bytesNeeded)
1239 *pcbStructInfo = bytesNeeded;
1240 SetLastError(ERROR_MORE_DATA);
1245 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1247 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
1249 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1250 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
1251 link->u.pwszFile[i] =
1252 hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
1253 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
1254 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
1259 bytesNeeded += sizeof(WCHAR);
1261 *pcbStructInfo = bytesNeeded;
1262 else if (*pcbStructInfo < bytesNeeded)
1264 *pcbStructInfo = bytesNeeded;
1265 SetLastError(ERROR_MORE_DATA);
1270 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1272 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1273 link->u.pwszFile[0] = '\0';
1279 SetLastError(CRYPT_E_ASN1_BADTAG);
1282 TRACE("returning %d\n", ret);
1286 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1287 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1288 void *pvStructInfo, DWORD *pcbStructInfo)
1292 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1293 pvStructInfo, *pcbStructInfo);
1299 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1300 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1304 *pcbStructInfo = bytesNeeded;
1305 else if (*pcbStructInfo < bytesNeeded)
1307 *pcbStructInfo = bytesNeeded;
1308 SetLastError(ERROR_MORE_DATA);
1313 SPC_LINK *link = (SPC_LINK *)pvStructInfo;
1316 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1317 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1318 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1325 SetLastError(STATUS_ACCESS_VIOLATION);
1328 TRACE("returning %d\n", ret);
1332 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1333 DWORD, DWORD, void *, DWORD *);
1336 * The expected tag of the item. If tag is 0, decodeFunc is called
1337 * regardless of the tag value seen.
1339 * A sequence is decoded into a struct. The offset member is the
1340 * offset of this item within that struct.
1342 * The decoder function to use. If this is NULL, then the member isn't
1343 * decoded, but minSize space is reserved for it.
1345 * The minimum amount of space occupied after decoding. You must set this.
1347 * If true, and the tag doesn't match the expected tag for this item,
1348 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1349 * filled with 0 for this member.
1350 * hasPointer, pointerOffset:
1351 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1352 * the offset within the struct of the data pointer (or to the
1353 * first data pointer, if more than one exist).
1355 * Used by CRYPT_AsnDecodeSequence, not for your use.
1357 struct AsnDecodeSequenceItem
1361 CryptDecodeObjectFunc decodeFunc;
1365 DWORD pointerOffset;
1369 /* Decodes the items in a sequence, where the items are described in items,
1370 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1371 * pvStructInfo. nextData is a pointer to the memory location at which the
1372 * first decoded item with a dynamic pointer should point.
1373 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1375 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1376 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1377 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1381 DWORD i, decoded = 0;
1382 const BYTE *ptr = pbEncoded;
1384 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1385 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1387 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1389 if (cbEncoded - (ptr - pbEncoded) != 0)
1393 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1396 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1398 if (ptr[0] == items[i].tag || !items[i].tag)
1400 if (nextData && pvStructInfo && items[i].hasPointer)
1402 TRACE("Setting next pointer to %p\n",
1404 *(BYTE **)((BYTE *)pvStructInfo +
1405 items[i].pointerOffset) = nextData;
1407 if (items[i].decodeFunc)
1410 TRACE("decoding item %d\n", i);
1412 TRACE("sizing item %d\n", i);
1413 ret = items[i].decodeFunc(dwCertEncodingType,
1414 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1415 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1416 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1417 : NULL, &items[i].size);
1420 /* Account for alignment padding */
1421 if (items[i].size % sizeof(DWORD))
1422 items[i].size += sizeof(DWORD) -
1423 items[i].size % sizeof(DWORD);
1424 TRACE("item %d size: %d\n", i, items[i].size);
1425 if (nextData && items[i].hasPointer &&
1426 items[i].size > items[i].minSize)
1427 nextData += items[i].size - items[i].minSize;
1428 ptr += 1 + nextItemLenBytes + nextItemLen;
1429 decoded += 1 + nextItemLenBytes + nextItemLen;
1430 TRACE("item %d: decoded %d bytes\n", i,
1431 1 + nextItemLenBytes + nextItemLen);
1433 else if (items[i].optional &&
1434 GetLastError() == CRYPT_E_ASN1_BADTAG)
1436 TRACE("skipping optional item %d\n", i);
1437 items[i].size = items[i].minSize;
1438 SetLastError(NOERROR);
1442 TRACE("item %d failed: %08x\n", i,
1447 TRACE("item %d: decoded %d bytes\n", i,
1448 1 + nextItemLenBytes + nextItemLen);
1449 ptr += 1 + nextItemLenBytes + nextItemLen;
1450 decoded += 1 + nextItemLenBytes + nextItemLen;
1451 items[i].size = items[i].minSize;
1454 else if (items[i].optional)
1456 TRACE("skipping optional item %d\n", i);
1457 items[i].size = items[i].minSize;
1461 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1462 i, ptr[0], items[i].tag);
1463 SetLastError(CRYPT_E_ASN1_BADTAG);
1468 else if (items[i].optional)
1470 TRACE("missing optional item %d, skipping\n", i);
1471 items[i].size = items[i].minSize;
1475 TRACE("not enough bytes for item %d, failing\n", i);
1476 SetLastError(CRYPT_E_ASN1_CORRUPT);
1481 *cbDecoded = decoded;
1482 TRACE("returning %d\n", ret);
1486 /* This decodes an arbitrary sequence into a contiguous block of memory
1487 * (basically, a struct.) Each element being decoded is described by a struct
1488 * AsnDecodeSequenceItem, see above.
1489 * startingPointer is an optional pointer to the first place where dynamic
1490 * data will be stored. If you know the starting offset, you may pass it
1491 * here. Otherwise, pass NULL, and one will be inferred from the items.
1493 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1494 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1495 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1496 void *startingPointer)
1500 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
1501 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1503 if (pbEncoded[0] == ASN_SEQUENCE)
1507 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1509 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1510 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1512 cbEncoded -= 1 + lenBytes;
1513 if (cbEncoded < dataLen)
1515 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
1517 SetLastError(CRYPT_E_ASN1_CORRUPT);
1521 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1522 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1523 if (ret && cbDecoded != dataLen)
1525 TRACE("expected %d decoded, got %d, failing\n", dataLen,
1527 SetLastError(CRYPT_E_ASN1_CORRUPT);
1532 DWORD i, bytesNeeded = 0, structSize = 0;
1534 for (i = 0; i < cItem; i++)
1536 bytesNeeded += items[i].size;
1537 structSize += items[i].minSize;
1540 *pcbStructInfo = bytesNeeded;
1541 else if (*pcbStructInfo < bytesNeeded)
1543 SetLastError(ERROR_MORE_DATA);
1544 *pcbStructInfo = bytesNeeded;
1551 *pcbStructInfo = bytesNeeded;
1552 if (startingPointer)
1553 nextData = (BYTE *)startingPointer;
1555 nextData = (BYTE *)pvStructInfo + structSize;
1556 memset(pvStructInfo, 0, structSize);
1557 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1558 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1566 SetLastError(CRYPT_E_ASN1_BADTAG);
1569 TRACE("returning %d (%08x)\n", ret, GetLastError());
1573 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1574 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1575 void *pvStructInfo, DWORD *pcbStructInfo)
1579 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
1580 pvStructInfo, *pcbStructInfo);
1582 if (pbEncoded[0] == ASN_BITSTRING)
1584 DWORD bytesNeeded, dataLen;
1586 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1588 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1589 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1591 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1593 *pcbStructInfo = bytesNeeded;
1594 else if (*pcbStructInfo < bytesNeeded)
1596 *pcbStructInfo = bytesNeeded;
1597 SetLastError(ERROR_MORE_DATA);
1602 CRYPT_BIT_BLOB *blob;
1604 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
1605 blob->cbData = dataLen - 1;
1606 blob->cUnusedBits = *(pbEncoded + 1 +
1607 GET_LEN_BYTES(pbEncoded[1]));
1608 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1610 blob->pbData = (BYTE *)pbEncoded + 2 +
1611 GET_LEN_BYTES(pbEncoded[1]);
1615 assert(blob->pbData);
1618 BYTE mask = 0xff << blob->cUnusedBits;
1620 memcpy(blob->pbData, pbEncoded + 2 +
1621 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1622 blob->pbData[blob->cbData - 1] &= mask;
1630 SetLastError(CRYPT_E_ASN1_BADTAG);
1633 TRACE("returning %d (%08x)\n", ret, GetLastError());
1637 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1638 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1639 void *pvStructInfo, DWORD *pcbStructInfo)
1644 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1646 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1648 SPC_LINK **pLink = (SPC_LINK **)pvStructInfo;
1650 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1651 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1655 *pcbStructInfo = size + sizeof(PSPC_LINK);
1656 else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1658 *pcbStructInfo = size + sizeof(PSPC_LINK);
1659 SetLastError(ERROR_MORE_DATA);
1664 *pcbStructInfo = size + sizeof(PSPC_LINK);
1665 /* Set imageData's pointer if necessary */
1666 if (size > sizeof(SPC_LINK))
1668 (*pLink)->u.pwszUrl =
1669 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1671 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1672 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1673 *pLink, pcbStructInfo);
1680 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1681 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1682 void *pvStructInfo, DWORD *pcbStructInfo)
1686 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1687 pvStructInfo, *pcbStructInfo);
1691 struct AsnDecodeSequenceItem items[] = {
1692 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1693 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1694 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1695 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1696 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1697 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1700 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1701 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1702 pvStructInfo, pcbStructInfo, NULL);
1706 SetLastError(STATUS_ACCESS_VIOLATION);
1709 TRACE("returning %d\n", ret);
1713 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1714 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1715 void *pvStructInfo, DWORD *pcbStructInfo)
1720 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1721 pvStructInfo, *pcbStructInfo);
1723 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1725 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1726 DWORD bytesNeeded = sizeof(LPSTR);
1730 /* The largest possible string for the first two components
1731 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1736 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1737 pbEncoded[1 + lenBytes] / 40,
1738 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1740 bytesNeeded += strlen(firstTwo) + 1;
1741 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1742 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1744 /* large enough for ".4000000" */
1748 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1755 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1758 SetLastError(CRYPT_E_ASN1_CORRUPT);
1765 snprintf(str, sizeof(str), ".%d", val);
1766 bytesNeeded += strlen(str);
1771 *pcbStructInfo = bytesNeeded;
1772 else if (*pcbStructInfo < bytesNeeded)
1774 *pcbStructInfo = bytesNeeded;
1775 SetLastError(ERROR_MORE_DATA);
1783 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1786 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1787 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1789 pszObjId += strlen(pszObjId);
1790 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1791 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1795 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1804 sprintf(pszObjId, ".%d", val);
1805 pszObjId += strlen(pszObjId);
1809 *(LPSTR *)pvStructInfo = NULL;
1810 *pcbStructInfo = bytesNeeded;
1816 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1817 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1818 void *pvStructInfo, DWORD *pcbStructInfo)
1822 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1823 pvStructInfo, *pcbStructInfo);
1826 SetLastError(CRYPT_E_ASN1_CORRUPT);
1827 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1828 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1829 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1831 SetLastError(CRYPT_E_ASN1_BADTAG);
1835 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1836 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1837 void *pvStructInfo, DWORD *pcbStructInfo)
1840 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1842 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1843 pvStructInfo, *pcbStructInfo);
1845 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1846 bytesNeeded += cbEncoded;
1848 *pcbStructInfo = bytesNeeded;
1849 else if (*pcbStructInfo < bytesNeeded)
1851 SetLastError(ERROR_MORE_DATA);
1852 *pcbStructInfo = bytesNeeded;
1857 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1859 *pcbStructInfo = bytesNeeded;
1860 blob->cbData = cbEncoded;
1861 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1862 blob->pbData = (LPBYTE)pbEncoded;
1865 assert(blob->pbData);
1866 memcpy(blob->pbData, pbEncoded, blob->cbData);
1872 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1873 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1874 void *pvStructInfo, DWORD *pcbStructInfo)
1876 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
1877 (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
1878 struct AsnDecodeSequenceItem items[] = {
1879 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1880 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1881 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1882 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1883 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1884 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1887 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1888 pvStructInfo, *pcbStructInfo);
1890 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1891 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1892 pvStructInfo, pcbStructInfo,
1893 typeValue ? typeValue->pszObjId : NULL);
1896 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1898 void *pvStructInfo, DWORD *pcbStructInfo)
1900 CRYPT_ALGORITHM_IDENTIFIER *algo =
1901 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1903 struct AsnDecodeSequenceItem items[] = {
1904 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1905 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1906 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1907 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1908 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1909 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1912 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1913 pvStructInfo, *pcbStructInfo);
1915 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1916 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1917 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1918 if (ret && pvStructInfo)
1920 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1921 debugstr_a(algo->pszObjId));
1926 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
1927 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1928 void *pvStructInfo, DWORD *pcbStructInfo)
1930 struct SPCDigest *digest =
1931 (struct SPCDigest *)pvStructInfo;
1932 struct AsnDecodeSequenceItem items[] = {
1933 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
1934 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1936 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
1937 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
1938 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
1939 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
1942 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1943 pvStructInfo, *pcbStructInfo);
1945 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1946 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1947 pvStructInfo, pcbStructInfo,
1948 digest ? digest->DigestAlgorithm.pszObjId : NULL);
1951 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
1952 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1953 void *pvStructInfo, DWORD *pcbStructInfo)
1957 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1958 pvStructInfo, *pcbStructInfo);
1962 struct AsnDecodeSequenceItem items[] = {
1963 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
1964 CRYPT_AsnDecodeAttributeTypeValue,
1965 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
1966 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
1967 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
1968 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
1970 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
1973 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1974 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1975 pvStructInfo, pcbStructInfo, NULL);
1979 SetLastError(STATUS_ACCESS_VIOLATION);
1982 TRACE("returning %d\n", ret);
1986 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
1987 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1988 void *pvStructInfo, DWORD *pcbStructInfo)
1990 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1991 pvStructInfo, *pcbStructInfo);
1995 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
1996 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1997 void *pvStructInfo, DWORD *pcbStructInfo)
2000 DWORD bytesNeeded, dataLen;
2002 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2004 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2006 bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
2008 *pcbStructInfo = bytesNeeded;
2009 else if (*pcbStructInfo < bytesNeeded)
2011 *pcbStructInfo = bytesNeeded;
2012 SetLastError(ERROR_MORE_DATA);
2020 *pcbStructInfo = bytesNeeded;
2021 assert(pvStructInfo);
2022 str = *(LPWSTR *)pvStructInfo;
2023 for (i = 0; i < dataLen / 2; i++)
2024 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2025 pbEncoded[1 + lenBytes + 2 * i + 1];
2026 /* Decoded string is always NULL-terminated */
2033 static BOOL CRYPT_AsnDecodeInteger(const BYTE *pbEncoded,
2034 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo)
2037 DWORD bytesNeeded, dataLen;
2039 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2041 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2043 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2045 *pcbStructInfo = bytesNeeded;
2046 else if (*pcbStructInfo < bytesNeeded)
2048 *pcbStructInfo = bytesNeeded;
2049 SetLastError(ERROR_MORE_DATA);
2054 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2056 *pcbStructInfo = bytesNeeded;
2057 blob->cbData = dataLen;
2058 assert(blob->pbData);
2063 for (i = 0; i < blob->cbData; i++)
2065 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2074 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2075 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2076 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2077 void *pvStructInfo, DWORD *pcbStructInfo)
2080 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2081 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2082 DWORD size = sizeof(buf);
2084 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2085 ret = CRYPT_AsnDecodeInteger(pbEncoded, cbEncoded, 0, buf, &size);
2089 *pcbStructInfo = sizeof(int);
2090 else if (*pcbStructInfo < sizeof(int))
2092 *pcbStructInfo = sizeof(int);
2093 SetLastError(ERROR_MORE_DATA);
2100 *pcbStructInfo = sizeof(int);
2101 if (blob->pbData[blob->cbData - 1] & 0x80)
2103 /* initialize to a negative value to sign-extend */
2108 for (i = 0; i < blob->cbData; i++)
2111 val |= blob->pbData[blob->cbData - i - 1];
2113 memcpy(pvStructInfo, &val, sizeof(int));
2116 else if (GetLastError() == ERROR_MORE_DATA)
2117 SetLastError(CRYPT_E_ASN1_LARGE);
2121 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
2122 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2123 void *pvStructInfo, DWORD *pcbStructInfo)
2127 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2128 pvStructInfo, *pcbStructInfo);
2132 struct AsnDecodeSequenceItem items[] = {
2133 { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
2134 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2135 offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
2136 { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
2137 CRYPT_AsnDecodeInt, sizeof(DWORD),
2138 FALSE, FALSE, 0, 0 },
2141 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2142 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2143 pvStructInfo, pcbStructInfo, NULL);
2147 SetLastError(STATUS_ACCESS_VIOLATION);
2150 TRACE("returning %d\n", ret);
2154 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
2155 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2156 void *pvStructInfo, DWORD *pcbStructInfo)
2160 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2161 pvStructInfo, *pcbStructInfo);
2165 struct AsnDecodeSequenceItem items[] = {
2166 { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
2167 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2168 offsetof(CAT_NAMEVALUE, pwszTag), 0 },
2169 { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
2170 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2171 { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
2172 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2173 offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
2176 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2177 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2178 pvStructInfo, pcbStructInfo, NULL);
2182 SetLastError(STATUS_ACCESS_VIOLATION);
2185 TRACE("returning %d\n", ret);
2189 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2190 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2191 void *pvStructInfo, DWORD *pcbStructInfo)
2197 SetLastError(CRYPT_E_ASN1_CORRUPT);
2200 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2202 SetLastError(CRYPT_E_ASN1_CORRUPT);
2205 if (pbEncoded[1] > 1)
2207 SetLastError(CRYPT_E_ASN1_CORRUPT);
2212 *pcbStructInfo = sizeof(BOOL);
2215 else if (*pcbStructInfo < sizeof(BOOL))
2217 *pcbStructInfo = sizeof(BOOL);
2218 SetLastError(ERROR_MORE_DATA);
2223 *pcbStructInfo = sizeof(BOOL);
2224 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2227 TRACE("returning %d (%08x)\n", ret, GetLastError());
2231 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType,
2232 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2233 void *pvStructInfo, DWORD *pcbStructInfo)
2237 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2238 pvStructInfo, *pcbStructInfo);
2242 struct AsnDecodeSequenceItem items[] = {
2243 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable),
2244 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2245 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria),
2246 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2249 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2250 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2251 pvStructInfo, pcbStructInfo, NULL);
2255 SetLastError(STATUS_ACCESS_VIOLATION);
2258 TRACE("returning %d\n", ret);