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
23 #define NONAMELESSUNION
31 #include "wine/debug.h"
32 #include "wine/exception.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
36 #ifdef WORDS_BIGENDIAN
43 #define hton16(x) RtlUshortByteSwap(x)
44 #define n16toh(x) RtlUshortByteSwap(x)
48 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
50 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
52 DWORD bytesNeeded, significantBytes = 0;
60 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
61 temp <<= 8, significantBytes--)
63 bytesNeeded = significantBytes + 1;
67 *pcbEncoded = bytesNeeded;
70 if (*pcbEncoded < bytesNeeded)
72 SetLastError(ERROR_MORE_DATA);
76 *pbEncoded = (BYTE)len;
81 *pbEncoded++ = significantBytes | 0x80;
82 for (i = 0; i < significantBytes; i++)
84 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
88 *pcbEncoded = bytesNeeded;
92 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
97 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
98 DWORD bytesNeeded, lenBytes;
100 TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
103 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
104 bytesNeeded = 1 + lenBytes + blob->cbData;
106 *pcbEncoded = bytesNeeded;
107 else if (*pcbEncoded < bytesNeeded)
109 *pcbEncoded = bytesNeeded;
110 SetLastError(ERROR_MORE_DATA);
115 *pbEncoded++ = ASN_OCTETSTRING;
116 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
117 pbEncoded += lenBytes;
119 memcpy(pbEncoded, blob->pbData, blob->cbData);
121 TRACE("returning %d\n", ret);
125 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
126 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
131 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
132 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
137 const SPC_LINK *link = (const SPC_LINK *)pvStructInfo;
138 DWORD bytesNeeded, lenBytes;
140 switch (link->dwLinkChoice)
142 case SPC_FILE_LINK_CHOICE:
144 DWORD fileNameLen, fileNameLenBytes;
147 fileNameLen = link->u.pwszFile ?
148 lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
149 CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
150 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
152 bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
155 *pcbEncoded = bytesNeeded;
158 else if (*pcbEncoded < bytesNeeded)
160 SetLastError(ERROR_MORE_DATA);
161 *pcbEncoded = bytesNeeded;
165 *pcbEncoded = bytesNeeded;
166 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
167 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
169 pbEncoded += lenBytes;
170 *pbEncoded++ = ASN_CONTEXT;
171 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
172 pbEncoded += fileNameLenBytes;
173 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
175 *(WCHAR *)pbEncoded = hton16(*ptr);
176 pbEncoded += sizeof(WCHAR);
182 case SPC_MONIKER_LINK_CHOICE:
184 DWORD classIdLenBytes, dataLenBytes, dataLen;
185 CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
186 (BYTE *)&link->u.Moniker.ClassId };
188 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
189 CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
191 dataLen = 2 + classIdLenBytes + classId.cbData +
192 dataLenBytes + link->u.Moniker.SerializedData.cbData;
193 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
194 bytesNeeded = 1 + dataLen + lenBytes;
197 *pcbEncoded = bytesNeeded;
200 else if (*pcbEncoded < bytesNeeded)
202 SetLastError(ERROR_MORE_DATA);
203 *pcbEncoded = bytesNeeded;
209 *pcbEncoded = bytesNeeded;
210 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
211 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
212 pbEncoded += lenBytes;
213 size = 1 + classIdLenBytes + classId.cbData;
214 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
217 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
218 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
219 &link->u.Moniker.SerializedData, pbEncoded, &size);
225 case SPC_URL_LINK_CHOICE:
230 /* Check for invalid characters in URL */
233 for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
237 SetLastError(CRYPT_E_INVALID_IA5_STRING);
244 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
245 bytesNeeded = 1 + lenBytes + urlLen;
247 *pcbEncoded = bytesNeeded;
248 else if (*pcbEncoded < bytesNeeded)
250 SetLastError(ERROR_MORE_DATA);
251 *pcbEncoded = bytesNeeded;
256 *pcbEncoded = bytesNeeded;
257 *pbEncoded++ = ASN_CONTEXT;
258 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
259 pbEncoded += lenBytes;
260 for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
261 *pbEncoded++ = (BYTE)*ptr;
267 SetLastError(E_INVALIDARG);
272 SetLastError(STATUS_ACCESS_VIOLATION);
275 TRACE("returning %d\n", ret);
279 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
282 struct AsnEncodeSequenceItem
284 const void *pvStructInfo;
285 CryptEncodeObjectFunc encodeFunc;
286 DWORD size; /* used during encoding, not for your use */
289 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
290 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
294 DWORD i, dataLen = 0;
296 TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
297 for (i = 0, ret = TRUE; ret && i < cItem; i++)
299 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
300 items[i].pvStructInfo, NULL, &items[i].size);
301 /* Some functions propagate their errors through the size */
303 *pcbEncoded = items[i].size;
304 dataLen += items[i].size;
308 DWORD lenBytes, bytesNeeded;
310 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
311 bytesNeeded = 1 + lenBytes + dataLen;
313 *pcbEncoded = bytesNeeded;
314 else if (*pcbEncoded < bytesNeeded)
316 *pcbEncoded = bytesNeeded;
317 SetLastError(ERROR_MORE_DATA);
322 *pcbEncoded = bytesNeeded;
323 *pbEncoded++ = ASN_SEQUENCE;
324 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
325 pbEncoded += lenBytes;
326 for (i = 0; ret && i < cItem; i++)
328 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
329 items[i].pvStructInfo, pbEncoded, &items[i].size);
330 /* Some functions propagate their errors through the size */
332 *pcbEncoded = items[i].size;
333 pbEncoded += items[i].size;
337 TRACE("returning %d\n", ret);
341 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
342 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
349 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
350 DWORD bytesNeeded, lenBytes, dataBytes;
353 /* yep, MS allows cUnusedBits to be >= 8 */
354 if (!blob->cUnusedBits)
356 dataBytes = blob->cbData;
359 else if (blob->cbData * 8 > blob->cUnusedBits)
361 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
362 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
370 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
371 bytesNeeded = 1 + lenBytes + dataBytes + 1;
374 *pcbEncoded = bytesNeeded;
377 else if (*pcbEncoded < bytesNeeded)
379 *pcbEncoded = bytesNeeded;
380 SetLastError(ERROR_MORE_DATA);
385 *pcbEncoded = bytesNeeded;
386 *pbEncoded++ = ASN_BITSTRING;
387 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
388 pbEncoded += lenBytes;
389 *pbEncoded++ = unusedBits;
392 BYTE mask = 0xff << unusedBits;
396 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
397 pbEncoded += dataBytes - 1;
399 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
405 SetLastError(STATUS_ACCESS_VIOLATION);
411 struct AsnConstructedItem
414 const void *pvStructInfo;
415 CryptEncodeObjectFunc encodeFunc;
418 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
419 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
423 const struct AsnConstructedItem *item =
424 (const struct AsnConstructedItem *)pvStructInfo;
427 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
428 item->pvStructInfo, NULL, &len)))
430 DWORD dataLen, bytesNeeded;
432 CRYPT_EncodeLen(len, NULL, &dataLen);
433 bytesNeeded = 1 + dataLen + len;
435 *pcbEncoded = bytesNeeded;
436 else if (*pcbEncoded < bytesNeeded)
438 *pcbEncoded = bytesNeeded;
439 SetLastError(ERROR_MORE_DATA);
444 *pcbEncoded = bytesNeeded;
445 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
446 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
447 pbEncoded += dataLen;
448 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
449 item->pvStructInfo, pbEncoded, &len);
452 /* Some functions propagate their errors through the size */
459 /* Some functions propagate their errors through the size */
466 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
467 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
470 const SPC_PE_IMAGE_DATA *imageData =
471 (const SPC_PE_IMAGE_DATA *)pvStructInfo;
474 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
475 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
480 struct AsnEncodeSequenceItem items[2] = {
483 struct AsnConstructedItem constructed = { 0, imageData->pFile,
484 WVTAsn1SpcLinkEncode };
487 if (imageData->Flags.cbData)
489 items[cItem].pvStructInfo = &imageData->Flags;
490 items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
493 if (imageData->pFile)
495 items[cItem].pvStructInfo = &constructed;
496 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
500 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
501 pbEncoded, pcbEncoded);
505 SetLastError(STATUS_ACCESS_VIOLATION);
508 TRACE("returning %d\n", ret);
512 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
513 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
516 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
517 DWORD bytesNeeded = 0, lenBytes;
522 TRACE("%s\n", debugstr_a(pszObjId));
529 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
531 SetLastError(CRYPT_E_ASN1_ERROR);
535 firstByte = val1 * 40 + val2;
536 ptr = pszObjId + firstPos;
541 /* note I assume each component is at most 32-bits long in base 2 */
542 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
544 if (val1 >= 0x10000000)
546 else if (val1 >= 0x200000)
548 else if (val1 >= 0x4000)
550 else if (val1 >= 0x80)
560 SetLastError(CRYPT_E_ASN1_ERROR);
564 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
568 bytesNeeded += 1 + lenBytes;
571 if (*pcbEncoded < bytesNeeded)
573 SetLastError(ERROR_MORE_DATA);
578 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
579 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
580 pbEncoded += lenBytes;
586 *pbEncoded++ = firstByte;
587 ptr = pszObjId + firstPos;
590 sscanf(ptr, "%d%n", &val, &pos);
592 unsigned char outBytes[5];
595 if (val >= 0x10000000)
597 else if (val >= 0x200000)
599 else if (val >= 0x4000)
601 else if (val >= 0x80)
605 for (i = numBytes; i > 0; i--)
607 outBytes[i - 1] = val & 0x7f;
610 for (i = 0; i < numBytes - 1; i++)
611 *pbEncoded++ = outBytes[i] | 0x80;
612 *pbEncoded++ = outBytes[i];
621 *pcbEncoded = bytesNeeded;
625 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
626 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
629 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
633 *pcbEncoded = blob->cbData;
634 else if (*pcbEncoded < blob->cbData)
636 *pcbEncoded = blob->cbData;
637 SetLastError(ERROR_MORE_DATA);
643 memcpy(pbEncoded, blob->pbData, blob->cbData);
644 *pcbEncoded = blob->cbData;
649 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
650 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
651 BYTE *pbEncoded, DWORD *pcbEncoded)
653 const CRYPT_ALGORITHM_IDENTIFIER *algo =
654 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
655 static const BYTE asn1Null[] = { ASN_NULL, 0 };
656 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
659 struct AsnEncodeSequenceItem items[2] = {
660 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
661 { NULL, CRYPT_CopyEncodedBlob, 0 },
664 if (algo->Parameters.cbData)
665 items[1].pvStructInfo = &algo->Parameters;
667 items[1].pvStructInfo = &nullBlob;
668 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
669 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
673 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
674 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
677 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
678 (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
679 struct AsnEncodeSequenceItem items[] = {
680 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
681 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
684 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
685 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
690 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
691 CRYPT_HASH_BLOB Digest;
694 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
695 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
698 const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
699 struct AsnEncodeSequenceItem items[] = {
700 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
701 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 },
704 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
705 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
708 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
709 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
714 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
715 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
719 const SPC_INDIRECT_DATA_CONTENT *data =
720 (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
721 struct AsnEncodeSequenceItem items[] = {
722 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
723 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
726 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
727 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
731 SetLastError(STATUS_ACCESS_VIOLATION);
737 /* Gets the number of length bytes from the given (leading) length byte */
738 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
740 /* Helper function to get the encoded length of the data starting at pbEncoded,
741 * where pbEncoded[0] is the tag. If the data are too short to contain a
742 * length or if the length is too large for cbEncoded, sets an appropriate
743 * error code and returns FALSE.
745 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
751 SetLastError(CRYPT_E_ASN1_CORRUPT);
754 else if (pbEncoded[1] <= 0x7f)
756 if (pbEncoded[1] + 1 > cbEncoded)
758 SetLastError(CRYPT_E_ASN1_EOD);
767 else if (pbEncoded[1] == 0x80)
769 FIXME("unimplemented for indefinite-length encoding\n");
770 SetLastError(CRYPT_E_ASN1_CORRUPT);
775 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
777 if (lenLen > sizeof(DWORD) + 1)
779 SetLastError(CRYPT_E_ASN1_LARGE);
782 else if (lenLen + 2 > cbEncoded)
784 SetLastError(CRYPT_E_ASN1_CORRUPT);
797 if (out + lenLen + 1 > cbEncoded)
799 SetLastError(CRYPT_E_ASN1_EOD);
812 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
813 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
814 void *pvStructInfo, DWORD *pcbStructInfo)
817 DWORD bytesNeeded, dataLen;
819 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
820 pvStructInfo, *pcbStructInfo);
824 SetLastError(CRYPT_E_ASN1_CORRUPT);
827 else if (pbEncoded[0] != ASN_OCTETSTRING)
829 SetLastError(CRYPT_E_ASN1_BADTAG);
832 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
834 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
835 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
837 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
839 *pcbStructInfo = bytesNeeded;
840 else if (*pcbStructInfo < bytesNeeded)
842 SetLastError(ERROR_MORE_DATA);
843 *pcbStructInfo = bytesNeeded;
848 CRYPT_DATA_BLOB *blob;
849 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
851 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
852 blob->cbData = dataLen;
853 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
854 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
857 assert(blob->pbData);
859 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
867 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
868 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
869 void *pvStructInfo, DWORD *pcbStructInfo)
872 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
874 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
875 pvStructInfo, *pcbStructInfo);
877 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
879 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
882 switch (pbEncoded[0])
885 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
887 *pcbStructInfo = bytesNeeded;
888 else if (*pcbStructInfo < bytesNeeded)
890 *pcbStructInfo = bytesNeeded;
891 SetLastError(ERROR_MORE_DATA);
896 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
899 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
900 for (i = 0; i < dataLen; i++)
902 *(pbEncoded + 1 + lenBytes + i);
903 link->u.pwszUrl[i] = '\0';
904 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
907 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
909 CRYPT_DATA_BLOB classId;
910 DWORD size = sizeof(classId);
912 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
913 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
914 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
916 if (classId.cbData != sizeof(SPC_UUID))
918 SetLastError(CRYPT_E_BAD_ENCODE);
923 CRYPT_DATA_BLOB data;
925 /* The tag length for the classId must be 1 since the
929 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
930 pbEncoded + 3 + lenBytes + classId.cbData,
931 cbEncoded - 3 - lenBytes - classId.cbData,
932 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
934 bytesNeeded += data.cbData;
936 *pcbStructInfo = bytesNeeded;
937 else if (*pcbStructInfo < bytesNeeded)
939 *pcbStructInfo = bytesNeeded;
940 SetLastError(ERROR_MORE_DATA);
945 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
947 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
948 /* pwszFile pointer was set by caller, copy it
949 * before overwriting it
951 link->u.Moniker.SerializedData.pbData =
952 (BYTE *)link->u.pwszFile;
953 memcpy(&link->u.Moniker.ClassId, classId.pbData,
955 memcpy(link->u.Moniker.SerializedData.pbData,
956 data.pbData, data.cbData);
957 link->u.Moniker.SerializedData.cbData = data.cbData;
964 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
965 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
966 SetLastError(CRYPT_E_ASN1_BADTAG);
967 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
970 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
972 bytesNeeded += realDataLen + sizeof(WCHAR);
974 *pcbStructInfo = bytesNeeded;
975 else if (*pcbStructInfo < bytesNeeded)
977 *pcbStructInfo = bytesNeeded;
978 SetLastError(ERROR_MORE_DATA);
983 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
985 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
987 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
988 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
989 link->u.pwszFile[i] =
990 hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
991 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
992 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
997 bytesNeeded += sizeof(WCHAR);
999 *pcbStructInfo = bytesNeeded;
1000 else if (*pcbStructInfo < bytesNeeded)
1002 *pcbStructInfo = bytesNeeded;
1003 SetLastError(ERROR_MORE_DATA);
1008 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1010 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1011 link->u.pwszFile[0] = '\0';
1017 SetLastError(CRYPT_E_ASN1_BADTAG);
1020 TRACE("returning %d\n", ret);
1024 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1025 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1026 void *pvStructInfo, DWORD *pcbStructInfo)
1030 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1031 pvStructInfo, *pcbStructInfo);
1037 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1038 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1042 *pcbStructInfo = bytesNeeded;
1043 else if (*pcbStructInfo < bytesNeeded)
1045 *pcbStructInfo = bytesNeeded;
1046 SetLastError(ERROR_MORE_DATA);
1051 SPC_LINK *link = (SPC_LINK *)pvStructInfo;
1054 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1055 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1056 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1063 SetLastError(STATUS_ACCESS_VIOLATION);
1066 TRACE("returning %d\n", ret);
1070 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1071 DWORD, DWORD, void *, DWORD *);
1074 * The expected tag of the item. If tag is 0, decodeFunc is called
1075 * regardless of the tag value seen.
1077 * A sequence is decoded into a struct. The offset member is the
1078 * offset of this item within that struct.
1080 * The decoder function to use. If this is NULL, then the member isn't
1081 * decoded, but minSize space is reserved for it.
1083 * The minimum amount of space occupied after decoding. You must set this.
1085 * If true, and the tag doesn't match the expected tag for this item,
1086 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1087 * filled with 0 for this member.
1088 * hasPointer, pointerOffset:
1089 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1090 * the offset within the struct of the data pointer (or to the
1091 * first data pointer, if more than one exist).
1093 * Used by CRYPT_AsnDecodeSequence, not for your use.
1095 struct AsnDecodeSequenceItem
1099 CryptDecodeObjectFunc decodeFunc;
1103 DWORD pointerOffset;
1107 /* Decodes the items in a sequence, where the items are described in items,
1108 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1109 * pvStructInfo. nextData is a pointer to the memory location at which the
1110 * first decoded item with a dynamic pointer should point.
1111 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1113 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1114 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1115 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1119 DWORD i, decoded = 0;
1120 const BYTE *ptr = pbEncoded;
1122 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1123 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1125 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1127 if (cbEncoded - (ptr - pbEncoded) != 0)
1131 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1134 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1136 if (ptr[0] == items[i].tag || !items[i].tag)
1138 if (nextData && pvStructInfo && items[i].hasPointer)
1140 TRACE("Setting next pointer to %p\n",
1142 *(BYTE **)((BYTE *)pvStructInfo +
1143 items[i].pointerOffset) = nextData;
1145 if (items[i].decodeFunc)
1148 TRACE("decoding item %d\n", i);
1150 TRACE("sizing item %d\n", i);
1151 ret = items[i].decodeFunc(dwCertEncodingType,
1152 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1153 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1154 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1155 : NULL, &items[i].size);
1158 /* Account for alignment padding */
1159 if (items[i].size % sizeof(DWORD))
1160 items[i].size += sizeof(DWORD) -
1161 items[i].size % sizeof(DWORD);
1162 TRACE("item %d size: %d\n", i, items[i].size);
1163 if (nextData && items[i].hasPointer &&
1164 items[i].size > items[i].minSize)
1165 nextData += items[i].size - items[i].minSize;
1166 ptr += 1 + nextItemLenBytes + nextItemLen;
1167 decoded += 1 + nextItemLenBytes + nextItemLen;
1168 TRACE("item %d: decoded %d bytes\n", i,
1169 1 + nextItemLenBytes + nextItemLen);
1171 else if (items[i].optional &&
1172 GetLastError() == CRYPT_E_ASN1_BADTAG)
1174 TRACE("skipping optional item %d\n", i);
1175 items[i].size = items[i].minSize;
1176 SetLastError(NOERROR);
1180 TRACE("item %d failed: %08x\n", i,
1185 TRACE("item %d: decoded %d bytes\n", i,
1186 1 + nextItemLenBytes + nextItemLen);
1187 ptr += 1 + nextItemLenBytes + nextItemLen;
1188 decoded += 1 + nextItemLenBytes + nextItemLen;
1189 items[i].size = items[i].minSize;
1192 else if (items[i].optional)
1194 TRACE("skipping optional item %d\n", i);
1195 items[i].size = items[i].minSize;
1199 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1200 i, ptr[0], items[i].tag);
1201 SetLastError(CRYPT_E_ASN1_BADTAG);
1206 else if (items[i].optional)
1208 TRACE("missing optional item %d, skipping\n", i);
1209 items[i].size = items[i].minSize;
1213 TRACE("not enough bytes for item %d, failing\n", i);
1214 SetLastError(CRYPT_E_ASN1_CORRUPT);
1219 *cbDecoded = decoded;
1220 TRACE("returning %d\n", ret);
1224 /* This decodes an arbitrary sequence into a contiguous block of memory
1225 * (basically, a struct.) Each element being decoded is described by a struct
1226 * AsnDecodeSequenceItem, see above.
1227 * startingPointer is an optional pointer to the first place where dynamic
1228 * data will be stored. If you know the starting offset, you may pass it
1229 * here. Otherwise, pass NULL, and one will be inferred from the items.
1231 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1232 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1233 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1234 void *startingPointer)
1238 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
1239 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1241 if (pbEncoded[0] == ASN_SEQUENCE)
1245 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1247 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1248 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1250 cbEncoded -= 1 + lenBytes;
1251 if (cbEncoded < dataLen)
1253 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
1255 SetLastError(CRYPT_E_ASN1_CORRUPT);
1259 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1260 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1261 if (ret && cbDecoded != dataLen)
1263 TRACE("expected %d decoded, got %d, failing\n", dataLen,
1265 SetLastError(CRYPT_E_ASN1_CORRUPT);
1270 DWORD i, bytesNeeded = 0, structSize = 0;
1272 for (i = 0; i < cItem; i++)
1274 bytesNeeded += items[i].size;
1275 structSize += items[i].minSize;
1278 *pcbStructInfo = bytesNeeded;
1279 else if (*pcbStructInfo < bytesNeeded)
1281 SetLastError(ERROR_MORE_DATA);
1282 *pcbStructInfo = bytesNeeded;
1289 *pcbStructInfo = bytesNeeded;
1290 if (startingPointer)
1291 nextData = (BYTE *)startingPointer;
1293 nextData = (BYTE *)pvStructInfo + structSize;
1294 memset(pvStructInfo, 0, structSize);
1295 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1296 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1304 SetLastError(CRYPT_E_ASN1_BADTAG);
1307 TRACE("returning %d (%08x)\n", ret, GetLastError());
1311 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1312 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1313 void *pvStructInfo, DWORD *pcbStructInfo)
1317 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
1318 pvStructInfo, *pcbStructInfo);
1320 if (pbEncoded[0] == ASN_BITSTRING)
1322 DWORD bytesNeeded, dataLen;
1324 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1326 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1327 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1329 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1331 *pcbStructInfo = bytesNeeded;
1332 else if (*pcbStructInfo < bytesNeeded)
1334 *pcbStructInfo = bytesNeeded;
1335 SetLastError(ERROR_MORE_DATA);
1340 CRYPT_BIT_BLOB *blob;
1342 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
1343 blob->cbData = dataLen - 1;
1344 blob->cUnusedBits = *(pbEncoded + 1 +
1345 GET_LEN_BYTES(pbEncoded[1]));
1346 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1348 blob->pbData = (BYTE *)pbEncoded + 2 +
1349 GET_LEN_BYTES(pbEncoded[1]);
1353 assert(blob->pbData);
1356 BYTE mask = 0xff << blob->cUnusedBits;
1358 memcpy(blob->pbData, pbEncoded + 2 +
1359 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1360 blob->pbData[blob->cbData - 1] &= mask;
1368 SetLastError(CRYPT_E_ASN1_BADTAG);
1371 TRACE("returning %d (%08x)\n", ret, GetLastError());
1375 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1376 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1377 void *pvStructInfo, DWORD *pcbStructInfo)
1382 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1384 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1386 SPC_LINK **pLink = (SPC_LINK **)pvStructInfo;
1388 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1389 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1393 *pcbStructInfo = size + sizeof(PSPC_LINK);
1394 else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1396 *pcbStructInfo = size + sizeof(PSPC_LINK);
1397 SetLastError(ERROR_MORE_DATA);
1402 *pcbStructInfo = size + sizeof(PSPC_LINK);
1403 /* Set imageData's pointer if necessary */
1404 if (size > sizeof(SPC_LINK))
1406 (*pLink)->u.pwszUrl =
1407 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1409 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1410 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1411 *pLink, pcbStructInfo);
1418 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1419 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1420 void *pvStructInfo, DWORD *pcbStructInfo)
1424 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1425 pvStructInfo, *pcbStructInfo);
1429 struct AsnDecodeSequenceItem items[] = {
1430 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1431 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1432 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1433 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1434 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1435 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1438 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1439 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1440 pvStructInfo, pcbStructInfo, NULL);
1444 SetLastError(STATUS_ACCESS_VIOLATION);
1447 TRACE("returning %d\n", ret);
1451 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1452 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1453 void *pvStructInfo, DWORD *pcbStructInfo)
1458 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1459 pvStructInfo, *pcbStructInfo);
1461 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1463 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1464 DWORD bytesNeeded = sizeof(LPSTR);
1468 /* The largest possible string for the first two components
1469 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1474 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1475 pbEncoded[1 + lenBytes] / 40,
1476 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1478 bytesNeeded += strlen(firstTwo) + 1;
1479 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1480 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1482 /* large enough for ".4000000" */
1486 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1493 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1496 SetLastError(CRYPT_E_ASN1_CORRUPT);
1503 snprintf(str, sizeof(str), ".%d", val);
1504 bytesNeeded += strlen(str);
1509 *pcbStructInfo = bytesNeeded;
1510 else if (*pcbStructInfo < bytesNeeded)
1512 *pcbStructInfo = bytesNeeded;
1513 SetLastError(ERROR_MORE_DATA);
1521 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1524 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1525 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1527 pszObjId += strlen(pszObjId);
1528 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1529 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1533 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1542 sprintf(pszObjId, ".%d", val);
1543 pszObjId += strlen(pszObjId);
1547 *(LPSTR *)pvStructInfo = NULL;
1548 *pcbStructInfo = bytesNeeded;
1554 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1555 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1556 void *pvStructInfo, DWORD *pcbStructInfo)
1560 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1561 pvStructInfo, *pcbStructInfo);
1564 SetLastError(CRYPT_E_ASN1_CORRUPT);
1565 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1566 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1567 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1569 SetLastError(CRYPT_E_ASN1_BADTAG);
1573 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1574 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1575 void *pvStructInfo, DWORD *pcbStructInfo)
1578 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1580 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1581 pvStructInfo, *pcbStructInfo);
1583 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1584 bytesNeeded += cbEncoded;
1586 *pcbStructInfo = bytesNeeded;
1587 else if (*pcbStructInfo < bytesNeeded)
1589 SetLastError(ERROR_MORE_DATA);
1590 *pcbStructInfo = bytesNeeded;
1595 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1597 *pcbStructInfo = bytesNeeded;
1598 blob->cbData = cbEncoded;
1599 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1600 blob->pbData = (LPBYTE)pbEncoded;
1603 assert(blob->pbData);
1604 memcpy(blob->pbData, pbEncoded, blob->cbData);
1610 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1611 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1612 void *pvStructInfo, DWORD *pcbStructInfo)
1614 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
1615 (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
1616 struct AsnDecodeSequenceItem items[] = {
1617 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1618 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1619 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1620 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1621 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1622 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1625 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1626 pvStructInfo, *pcbStructInfo);
1628 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1629 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1630 pvStructInfo, pcbStructInfo,
1631 typeValue ? typeValue->pszObjId : NULL);
1634 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1635 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1636 void *pvStructInfo, DWORD *pcbStructInfo)
1638 CRYPT_ALGORITHM_IDENTIFIER *algo =
1639 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1641 struct AsnDecodeSequenceItem items[] = {
1642 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1643 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1644 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1645 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1646 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1647 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1650 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1651 pvStructInfo, *pcbStructInfo);
1653 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1654 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1655 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1656 if (ret && pvStructInfo)
1658 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1659 debugstr_a(algo->pszObjId));
1664 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
1665 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1666 void *pvStructInfo, DWORD *pcbStructInfo)
1668 struct SPCDigest *digest =
1669 (struct SPCDigest *)pvStructInfo;
1670 struct AsnDecodeSequenceItem items[] = {
1671 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
1672 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1674 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
1675 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
1676 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
1677 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
1680 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1681 pvStructInfo, *pcbStructInfo);
1683 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1684 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1685 pvStructInfo, pcbStructInfo,
1686 digest ? digest->DigestAlgorithm.pszObjId : NULL);
1689 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
1690 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1691 void *pvStructInfo, DWORD *pcbStructInfo)
1695 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1696 pvStructInfo, *pcbStructInfo);
1700 struct AsnDecodeSequenceItem items[] = {
1701 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
1702 CRYPT_AsnDecodeAttributeTypeValue,
1703 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
1704 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
1705 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
1706 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
1708 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
1711 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1712 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1713 pvStructInfo, pcbStructInfo, NULL);
1717 SetLastError(STATUS_ACCESS_VIOLATION);
1720 TRACE("returning %d\n", ret);
1724 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
1725 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1726 void *pvStructInfo, DWORD *pcbStructInfo)
1728 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1729 pvStructInfo, *pcbStructInfo);