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_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
54 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
56 DWORD bytesNeeded, significantBytes = 0;
64 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
65 temp <<= 8, significantBytes--)
67 bytesNeeded = significantBytes + 1;
71 *pcbEncoded = bytesNeeded;
74 if (*pcbEncoded < bytesNeeded)
76 SetLastError(ERROR_MORE_DATA);
80 *pbEncoded = (BYTE)len;
85 *pbEncoded++ = significantBytes | 0x80;
86 for (i = 0; i < significantBytes; i++)
88 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
92 *pcbEncoded = bytesNeeded;
96 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
101 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
102 DWORD bytesNeeded, lenBytes;
104 TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
107 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
108 bytesNeeded = 1 + lenBytes + blob->cbData;
110 *pcbEncoded = bytesNeeded;
111 else if (*pcbEncoded < bytesNeeded)
113 *pcbEncoded = bytesNeeded;
114 SetLastError(ERROR_MORE_DATA);
119 *pbEncoded++ = ASN_OCTETSTRING;
120 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
121 pbEncoded += lenBytes;
123 memcpy(pbEncoded, blob->pbData, blob->cbData);
125 TRACE("returning %d\n", ret);
129 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
130 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
135 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
141 const SPC_LINK *link = (const SPC_LINK *)pvStructInfo;
142 DWORD bytesNeeded, lenBytes;
144 switch (link->dwLinkChoice)
146 case SPC_FILE_LINK_CHOICE:
148 DWORD fileNameLen, fileNameLenBytes;
151 fileNameLen = link->u.pwszFile ?
152 lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
153 CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
154 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
156 bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
159 *pcbEncoded = bytesNeeded;
162 else if (*pcbEncoded < bytesNeeded)
164 SetLastError(ERROR_MORE_DATA);
165 *pcbEncoded = bytesNeeded;
169 *pcbEncoded = bytesNeeded;
170 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
171 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
173 pbEncoded += lenBytes;
174 *pbEncoded++ = ASN_CONTEXT;
175 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
176 pbEncoded += fileNameLenBytes;
177 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
179 *(WCHAR *)pbEncoded = hton16(*ptr);
180 pbEncoded += sizeof(WCHAR);
186 case SPC_MONIKER_LINK_CHOICE:
188 DWORD classIdLenBytes, dataLenBytes, dataLen;
189 CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
190 (BYTE *)link->u.Moniker.ClassId };
192 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
193 CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
195 dataLen = 2 + classIdLenBytes + classId.cbData +
196 dataLenBytes + link->u.Moniker.SerializedData.cbData;
197 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
198 bytesNeeded = 1 + dataLen + lenBytes;
201 *pcbEncoded = bytesNeeded;
204 else if (*pcbEncoded < bytesNeeded)
206 SetLastError(ERROR_MORE_DATA);
207 *pcbEncoded = bytesNeeded;
213 *pcbEncoded = bytesNeeded;
214 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
215 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
216 pbEncoded += lenBytes;
217 size = 1 + classIdLenBytes + classId.cbData;
218 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
221 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
222 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
223 &link->u.Moniker.SerializedData, pbEncoded, &size);
229 case SPC_URL_LINK_CHOICE:
234 /* Check for invalid characters in URL */
237 for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
241 SetLastError(CRYPT_E_INVALID_IA5_STRING);
248 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
249 bytesNeeded = 1 + lenBytes + urlLen;
251 *pcbEncoded = bytesNeeded;
252 else if (*pcbEncoded < bytesNeeded)
254 SetLastError(ERROR_MORE_DATA);
255 *pcbEncoded = bytesNeeded;
260 *pcbEncoded = bytesNeeded;
261 *pbEncoded++ = ASN_CONTEXT;
262 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
263 pbEncoded += lenBytes;
264 for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
265 *pbEncoded++ = (BYTE)*ptr;
271 SetLastError(E_INVALIDARG);
276 SetLastError(STATUS_ACCESS_VIOLATION);
279 TRACE("returning %d\n", ret);
283 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
286 struct AsnEncodeSequenceItem
288 const void *pvStructInfo;
289 CryptEncodeObjectFunc encodeFunc;
290 DWORD size; /* used during encoding, not for your use */
293 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
294 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
298 DWORD i, dataLen = 0;
300 TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
301 for (i = 0, ret = TRUE; ret && i < cItem; i++)
303 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
304 items[i].pvStructInfo, NULL, &items[i].size);
305 /* Some functions propagate their errors through the size */
307 *pcbEncoded = items[i].size;
308 dataLen += items[i].size;
312 DWORD lenBytes, bytesNeeded;
314 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
315 bytesNeeded = 1 + lenBytes + dataLen;
317 *pcbEncoded = bytesNeeded;
318 else if (*pcbEncoded < bytesNeeded)
320 *pcbEncoded = bytesNeeded;
321 SetLastError(ERROR_MORE_DATA);
326 *pcbEncoded = bytesNeeded;
327 *pbEncoded++ = ASN_SEQUENCE;
328 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
329 pbEncoded += lenBytes;
330 for (i = 0; ret && i < cItem; i++)
332 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
333 items[i].pvStructInfo, pbEncoded, &items[i].size);
334 /* Some functions propagate their errors through the size */
336 *pcbEncoded = items[i].size;
337 pbEncoded += items[i].size;
341 TRACE("returning %d\n", ret);
345 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
346 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
353 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
354 DWORD bytesNeeded, lenBytes, dataBytes;
357 /* yep, MS allows cUnusedBits to be >= 8 */
358 if (!blob->cUnusedBits)
360 dataBytes = blob->cbData;
363 else if (blob->cbData * 8 > blob->cUnusedBits)
365 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
366 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
374 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
375 bytesNeeded = 1 + lenBytes + dataBytes + 1;
378 *pcbEncoded = bytesNeeded;
381 else if (*pcbEncoded < bytesNeeded)
383 *pcbEncoded = bytesNeeded;
384 SetLastError(ERROR_MORE_DATA);
389 *pcbEncoded = bytesNeeded;
390 *pbEncoded++ = ASN_BITSTRING;
391 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
392 pbEncoded += lenBytes;
393 *pbEncoded++ = unusedBits;
396 BYTE mask = 0xff << unusedBits;
400 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
401 pbEncoded += dataBytes - 1;
403 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
409 SetLastError(STATUS_ACCESS_VIOLATION);
415 struct AsnConstructedItem
418 const void *pvStructInfo;
419 CryptEncodeObjectFunc encodeFunc;
422 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
423 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
427 const struct AsnConstructedItem *item =
428 (const struct AsnConstructedItem *)pvStructInfo;
431 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
432 item->pvStructInfo, NULL, &len)))
434 DWORD dataLen, bytesNeeded;
436 CRYPT_EncodeLen(len, NULL, &dataLen);
437 bytesNeeded = 1 + dataLen + len;
439 *pcbEncoded = bytesNeeded;
440 else if (*pcbEncoded < bytesNeeded)
442 *pcbEncoded = bytesNeeded;
443 SetLastError(ERROR_MORE_DATA);
448 *pcbEncoded = bytesNeeded;
449 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
450 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
451 pbEncoded += dataLen;
452 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
453 item->pvStructInfo, pbEncoded, &len);
456 /* Some functions propagate their errors through the size */
463 /* Some functions propagate their errors through the size */
470 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
471 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
474 const SPC_PE_IMAGE_DATA *imageData =
475 (const SPC_PE_IMAGE_DATA *)pvStructInfo;
478 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
479 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
484 struct AsnEncodeSequenceItem items[2] = {
487 struct AsnConstructedItem constructed = { 0, imageData->pFile,
488 WVTAsn1SpcLinkEncode };
491 if (imageData->Flags.cbData)
493 items[cItem].pvStructInfo = &imageData->Flags;
494 items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
497 if (imageData->pFile)
499 items[cItem].pvStructInfo = &constructed;
500 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
504 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
505 pbEncoded, pcbEncoded);
509 SetLastError(STATUS_ACCESS_VIOLATION);
512 TRACE("returning %d\n", ret);
516 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
517 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
520 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
521 DWORD bytesNeeded = 0, lenBytes;
526 TRACE("%s\n", debugstr_a(pszObjId));
533 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
535 SetLastError(CRYPT_E_ASN1_ERROR);
539 firstByte = val1 * 40 + val2;
540 ptr = pszObjId + firstPos;
545 /* note I assume each component is at most 32-bits long in base 2 */
546 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
548 if (val1 >= 0x10000000)
550 else if (val1 >= 0x200000)
552 else if (val1 >= 0x4000)
554 else if (val1 >= 0x80)
564 SetLastError(CRYPT_E_ASN1_ERROR);
568 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
572 bytesNeeded += 1 + lenBytes;
575 if (*pcbEncoded < bytesNeeded)
577 SetLastError(ERROR_MORE_DATA);
582 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
583 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
584 pbEncoded += lenBytes;
590 *pbEncoded++ = firstByte;
591 ptr = pszObjId + firstPos;
594 sscanf(ptr, "%d%n", &val, &pos);
596 unsigned char outBytes[5];
599 if (val >= 0x10000000)
601 else if (val >= 0x200000)
603 else if (val >= 0x4000)
605 else if (val >= 0x80)
609 for (i = numBytes; i > 0; i--)
611 outBytes[i - 1] = val & 0x7f;
614 for (i = 0; i < numBytes - 1; i++)
615 *pbEncoded++ = outBytes[i] | 0x80;
616 *pbEncoded++ = outBytes[i];
625 *pcbEncoded = bytesNeeded;
629 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
630 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
633 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
637 *pcbEncoded = blob->cbData;
638 else if (*pcbEncoded < blob->cbData)
640 *pcbEncoded = blob->cbData;
641 SetLastError(ERROR_MORE_DATA);
647 memcpy(pbEncoded, blob->pbData, blob->cbData);
648 *pcbEncoded = blob->cbData;
653 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
654 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
655 BYTE *pbEncoded, DWORD *pcbEncoded)
657 const CRYPT_ALGORITHM_IDENTIFIER *algo =
658 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
659 static const BYTE asn1Null[] = { ASN_NULL, 0 };
660 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
663 struct AsnEncodeSequenceItem items[2] = {
664 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
665 { NULL, CRYPT_CopyEncodedBlob, 0 },
668 if (algo->Parameters.cbData)
669 items[1].pvStructInfo = &algo->Parameters;
671 items[1].pvStructInfo = &nullBlob;
672 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
673 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
677 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
678 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
681 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
682 (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
683 struct AsnEncodeSequenceItem items[] = {
684 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
685 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
688 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
689 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
694 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
695 CRYPT_HASH_BLOB Digest;
698 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
699 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
702 const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
703 struct AsnEncodeSequenceItem items[] = {
704 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
705 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 },
708 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
709 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
712 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
713 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
718 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
719 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
723 const SPC_INDIRECT_DATA_CONTENT *data =
724 (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
725 struct AsnEncodeSequenceItem items[] = {
726 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
727 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
730 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
731 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
735 SetLastError(STATUS_ACCESS_VIOLATION);
741 /* Gets the number of length bytes from the given (leading) length byte */
742 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
744 /* Helper function to get the encoded length of the data starting at pbEncoded,
745 * where pbEncoded[0] is the tag. If the data are too short to contain a
746 * length or if the length is too large for cbEncoded, sets an appropriate
747 * error code and returns FALSE.
749 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
755 SetLastError(CRYPT_E_ASN1_CORRUPT);
758 else if (pbEncoded[1] <= 0x7f)
760 if (pbEncoded[1] + 1 > cbEncoded)
762 SetLastError(CRYPT_E_ASN1_EOD);
771 else if (pbEncoded[1] == 0x80)
773 FIXME("unimplemented for indefinite-length encoding\n");
774 SetLastError(CRYPT_E_ASN1_CORRUPT);
779 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
781 if (lenLen > sizeof(DWORD) + 1)
783 SetLastError(CRYPT_E_ASN1_LARGE);
786 else if (lenLen + 2 > cbEncoded)
788 SetLastError(CRYPT_E_ASN1_CORRUPT);
801 if (out + lenLen + 1 > cbEncoded)
803 SetLastError(CRYPT_E_ASN1_EOD);
816 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
817 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
818 void *pvStructInfo, DWORD *pcbStructInfo)
821 DWORD bytesNeeded, dataLen;
823 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
824 pvStructInfo, *pcbStructInfo);
828 SetLastError(CRYPT_E_ASN1_CORRUPT);
831 else if (pbEncoded[0] != ASN_OCTETSTRING)
833 SetLastError(CRYPT_E_ASN1_BADTAG);
836 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
838 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
839 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
841 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
843 *pcbStructInfo = bytesNeeded;
844 else if (*pcbStructInfo < bytesNeeded)
846 SetLastError(ERROR_MORE_DATA);
847 *pcbStructInfo = bytesNeeded;
852 CRYPT_DATA_BLOB *blob;
853 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
855 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
856 blob->cbData = dataLen;
857 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
858 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
861 assert(blob->pbData);
863 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
871 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
872 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
873 void *pvStructInfo, DWORD *pcbStructInfo)
876 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
878 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
879 pvStructInfo, *pcbStructInfo);
881 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
883 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
886 switch (pbEncoded[0])
889 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
891 *pcbStructInfo = bytesNeeded;
892 else if (*pcbStructInfo < bytesNeeded)
894 *pcbStructInfo = bytesNeeded;
895 SetLastError(ERROR_MORE_DATA);
900 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
903 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
904 for (i = 0; i < dataLen; i++)
906 *(pbEncoded + 1 + lenBytes + i);
907 link->u.pwszUrl[i] = '\0';
908 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
911 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
913 CRYPT_DATA_BLOB classId;
914 DWORD size = sizeof(classId);
916 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
917 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
918 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
920 if (classId.cbData != sizeof(SPC_UUID))
922 SetLastError(CRYPT_E_BAD_ENCODE);
927 CRYPT_DATA_BLOB data;
929 /* The tag length for the classId must be 1 since the
933 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
934 pbEncoded + 3 + lenBytes + classId.cbData,
935 cbEncoded - 3 - lenBytes - classId.cbData,
936 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
938 bytesNeeded += data.cbData;
940 *pcbStructInfo = bytesNeeded;
941 else if (*pcbStructInfo < bytesNeeded)
943 *pcbStructInfo = bytesNeeded;
944 SetLastError(ERROR_MORE_DATA);
949 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
951 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
952 /* pwszFile pointer was set by caller, copy it
953 * before overwriting it
955 link->u.Moniker.SerializedData.pbData =
956 (BYTE *)link->u.pwszFile;
957 memcpy(link->u.Moniker.ClassId, classId.pbData,
959 memcpy(link->u.Moniker.SerializedData.pbData,
960 data.pbData, data.cbData);
961 link->u.Moniker.SerializedData.cbData = data.cbData;
968 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
969 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
970 SetLastError(CRYPT_E_ASN1_BADTAG);
971 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
974 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
976 bytesNeeded += realDataLen + sizeof(WCHAR);
978 *pcbStructInfo = bytesNeeded;
979 else if (*pcbStructInfo < bytesNeeded)
981 *pcbStructInfo = bytesNeeded;
982 SetLastError(ERROR_MORE_DATA);
987 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
989 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
991 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
992 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
993 link->u.pwszFile[i] =
994 hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
995 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
996 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
1001 bytesNeeded += sizeof(WCHAR);
1003 *pcbStructInfo = bytesNeeded;
1004 else if (*pcbStructInfo < bytesNeeded)
1006 *pcbStructInfo = bytesNeeded;
1007 SetLastError(ERROR_MORE_DATA);
1012 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1014 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1015 link->u.pwszFile[0] = '\0';
1021 SetLastError(CRYPT_E_ASN1_BADTAG);
1024 TRACE("returning %d\n", ret);
1028 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1029 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1030 void *pvStructInfo, DWORD *pcbStructInfo)
1034 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1035 pvStructInfo, *pcbStructInfo);
1041 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1042 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1046 *pcbStructInfo = bytesNeeded;
1047 else if (*pcbStructInfo < bytesNeeded)
1049 *pcbStructInfo = bytesNeeded;
1050 SetLastError(ERROR_MORE_DATA);
1055 SPC_LINK *link = (SPC_LINK *)pvStructInfo;
1058 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1059 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1060 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1067 SetLastError(STATUS_ACCESS_VIOLATION);
1070 TRACE("returning %d\n", ret);
1074 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1075 DWORD, DWORD, void *, DWORD *);
1078 * The expected tag of the item. If tag is 0, decodeFunc is called
1079 * regardless of the tag value seen.
1081 * A sequence is decoded into a struct. The offset member is the
1082 * offset of this item within that struct.
1084 * The decoder function to use. If this is NULL, then the member isn't
1085 * decoded, but minSize space is reserved for it.
1087 * The minimum amount of space occupied after decoding. You must set this.
1089 * If true, and the tag doesn't match the expected tag for this item,
1090 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1091 * filled with 0 for this member.
1092 * hasPointer, pointerOffset:
1093 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1094 * the offset within the struct of the data pointer (or to the
1095 * first data pointer, if more than one exist).
1097 * Used by CRYPT_AsnDecodeSequence, not for your use.
1099 struct AsnDecodeSequenceItem
1103 CryptDecodeObjectFunc decodeFunc;
1107 DWORD pointerOffset;
1111 /* Decodes the items in a sequence, where the items are described in items,
1112 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1113 * pvStructInfo. nextData is a pointer to the memory location at which the
1114 * first decoded item with a dynamic pointer should point.
1115 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1117 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1118 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1119 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1123 DWORD i, decoded = 0;
1124 const BYTE *ptr = pbEncoded;
1126 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1127 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1129 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1131 if (cbEncoded - (ptr - pbEncoded) != 0)
1135 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1138 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1140 if (ptr[0] == items[i].tag || !items[i].tag)
1142 if (nextData && pvStructInfo && items[i].hasPointer)
1144 TRACE("Setting next pointer to %p\n",
1146 *(BYTE **)((BYTE *)pvStructInfo +
1147 items[i].pointerOffset) = nextData;
1149 if (items[i].decodeFunc)
1152 TRACE("decoding item %d\n", i);
1154 TRACE("sizing item %d\n", i);
1155 ret = items[i].decodeFunc(dwCertEncodingType,
1156 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1157 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1158 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1159 : NULL, &items[i].size);
1162 /* Account for alignment padding */
1163 if (items[i].size % sizeof(DWORD))
1164 items[i].size += sizeof(DWORD) -
1165 items[i].size % sizeof(DWORD);
1166 TRACE("item %d size: %d\n", i, items[i].size);
1167 if (nextData && items[i].hasPointer &&
1168 items[i].size > items[i].minSize)
1169 nextData += items[i].size - items[i].minSize;
1170 ptr += 1 + nextItemLenBytes + nextItemLen;
1171 decoded += 1 + nextItemLenBytes + nextItemLen;
1172 TRACE("item %d: decoded %d bytes\n", i,
1173 1 + nextItemLenBytes + nextItemLen);
1175 else if (items[i].optional &&
1176 GetLastError() == CRYPT_E_ASN1_BADTAG)
1178 TRACE("skipping optional item %d\n", i);
1179 items[i].size = items[i].minSize;
1180 SetLastError(NOERROR);
1184 TRACE("item %d failed: %08x\n", i,
1189 TRACE("item %d: decoded %d bytes\n", i,
1190 1 + nextItemLenBytes + nextItemLen);
1191 ptr += 1 + nextItemLenBytes + nextItemLen;
1192 decoded += 1 + nextItemLenBytes + nextItemLen;
1193 items[i].size = items[i].minSize;
1196 else if (items[i].optional)
1198 TRACE("skipping optional item %d\n", i);
1199 items[i].size = items[i].minSize;
1203 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1204 i, ptr[0], items[i].tag);
1205 SetLastError(CRYPT_E_ASN1_BADTAG);
1210 else if (items[i].optional)
1212 TRACE("missing optional item %d, skipping\n", i);
1213 items[i].size = items[i].minSize;
1217 TRACE("not enough bytes for item %d, failing\n", i);
1218 SetLastError(CRYPT_E_ASN1_CORRUPT);
1223 *cbDecoded = decoded;
1224 TRACE("returning %d\n", ret);
1228 /* This decodes an arbitrary sequence into a contiguous block of memory
1229 * (basically, a struct.) Each element being decoded is described by a struct
1230 * AsnDecodeSequenceItem, see above.
1231 * startingPointer is an optional pointer to the first place where dynamic
1232 * data will be stored. If you know the starting offset, you may pass it
1233 * here. Otherwise, pass NULL, and one will be inferred from the items.
1235 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1236 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1237 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1238 void *startingPointer)
1242 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
1243 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1245 if (pbEncoded[0] == ASN_SEQUENCE)
1249 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1251 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1252 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1254 cbEncoded -= 1 + lenBytes;
1255 if (cbEncoded < dataLen)
1257 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
1259 SetLastError(CRYPT_E_ASN1_CORRUPT);
1263 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1264 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1265 if (ret && cbDecoded != dataLen)
1267 TRACE("expected %d decoded, got %d, failing\n", dataLen,
1269 SetLastError(CRYPT_E_ASN1_CORRUPT);
1274 DWORD i, bytesNeeded = 0, structSize = 0;
1276 for (i = 0; i < cItem; i++)
1278 bytesNeeded += items[i].size;
1279 structSize += items[i].minSize;
1282 *pcbStructInfo = bytesNeeded;
1283 else if (*pcbStructInfo < bytesNeeded)
1285 SetLastError(ERROR_MORE_DATA);
1286 *pcbStructInfo = bytesNeeded;
1293 *pcbStructInfo = bytesNeeded;
1294 if (startingPointer)
1295 nextData = (BYTE *)startingPointer;
1297 nextData = (BYTE *)pvStructInfo + structSize;
1298 memset(pvStructInfo, 0, structSize);
1299 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1300 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1308 SetLastError(CRYPT_E_ASN1_BADTAG);
1311 TRACE("returning %d (%08x)\n", ret, GetLastError());
1315 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1316 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1317 void *pvStructInfo, DWORD *pcbStructInfo)
1321 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
1322 pvStructInfo, *pcbStructInfo);
1324 if (pbEncoded[0] == ASN_BITSTRING)
1326 DWORD bytesNeeded, dataLen;
1328 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1330 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1331 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1333 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1335 *pcbStructInfo = bytesNeeded;
1336 else if (*pcbStructInfo < bytesNeeded)
1338 *pcbStructInfo = bytesNeeded;
1339 SetLastError(ERROR_MORE_DATA);
1344 CRYPT_BIT_BLOB *blob;
1346 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
1347 blob->cbData = dataLen - 1;
1348 blob->cUnusedBits = *(pbEncoded + 1 +
1349 GET_LEN_BYTES(pbEncoded[1]));
1350 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1352 blob->pbData = (BYTE *)pbEncoded + 2 +
1353 GET_LEN_BYTES(pbEncoded[1]);
1357 assert(blob->pbData);
1360 BYTE mask = 0xff << blob->cUnusedBits;
1362 memcpy(blob->pbData, pbEncoded + 2 +
1363 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1364 blob->pbData[blob->cbData - 1] &= mask;
1372 SetLastError(CRYPT_E_ASN1_BADTAG);
1375 TRACE("returning %d (%08x)\n", ret, GetLastError());
1379 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1380 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1381 void *pvStructInfo, DWORD *pcbStructInfo)
1386 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1388 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1390 SPC_LINK **pLink = (SPC_LINK **)pvStructInfo;
1392 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1393 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1397 *pcbStructInfo = size + sizeof(PSPC_LINK);
1398 else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1400 *pcbStructInfo = size + sizeof(PSPC_LINK);
1401 SetLastError(ERROR_MORE_DATA);
1406 *pcbStructInfo = size + sizeof(PSPC_LINK);
1407 /* Set imageData's pointer if necessary */
1408 if (size > sizeof(SPC_LINK))
1410 (*pLink)->u.pwszUrl =
1411 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1413 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1414 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1415 *pLink, pcbStructInfo);
1422 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1423 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1424 void *pvStructInfo, DWORD *pcbStructInfo)
1428 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1429 pvStructInfo, *pcbStructInfo);
1433 struct AsnDecodeSequenceItem items[] = {
1434 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1435 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1436 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1437 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1438 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1439 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1442 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1443 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1444 pvStructInfo, pcbStructInfo, NULL);
1448 SetLastError(STATUS_ACCESS_VIOLATION);
1451 TRACE("returning %d\n", ret);
1455 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1456 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1457 void *pvStructInfo, DWORD *pcbStructInfo)
1462 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1463 pvStructInfo, *pcbStructInfo);
1465 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1467 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1468 DWORD bytesNeeded = sizeof(LPSTR);
1472 /* The largest possible string for the first two components
1473 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1478 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1479 pbEncoded[1 + lenBytes] / 40,
1480 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1482 bytesNeeded += strlen(firstTwo) + 1;
1483 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1484 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1486 /* large enough for ".4000000" */
1490 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1497 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1500 SetLastError(CRYPT_E_ASN1_CORRUPT);
1507 snprintf(str, sizeof(str), ".%d", val);
1508 bytesNeeded += strlen(str);
1513 *pcbStructInfo = bytesNeeded;
1514 else if (*pcbStructInfo < bytesNeeded)
1516 *pcbStructInfo = bytesNeeded;
1517 SetLastError(ERROR_MORE_DATA);
1525 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1528 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1529 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1531 pszObjId += strlen(pszObjId);
1532 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1533 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1537 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1546 sprintf(pszObjId, ".%d", val);
1547 pszObjId += strlen(pszObjId);
1551 *(LPSTR *)pvStructInfo = NULL;
1552 *pcbStructInfo = bytesNeeded;
1558 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1559 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1560 void *pvStructInfo, DWORD *pcbStructInfo)
1564 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1565 pvStructInfo, *pcbStructInfo);
1568 SetLastError(CRYPT_E_ASN1_CORRUPT);
1569 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1570 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1571 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1573 SetLastError(CRYPT_E_ASN1_BADTAG);
1577 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1578 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1579 void *pvStructInfo, DWORD *pcbStructInfo)
1582 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1584 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1585 pvStructInfo, *pcbStructInfo);
1587 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1588 bytesNeeded += cbEncoded;
1590 *pcbStructInfo = bytesNeeded;
1591 else if (*pcbStructInfo < bytesNeeded)
1593 SetLastError(ERROR_MORE_DATA);
1594 *pcbStructInfo = bytesNeeded;
1599 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1601 *pcbStructInfo = bytesNeeded;
1602 blob->cbData = cbEncoded;
1603 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1604 blob->pbData = (LPBYTE)pbEncoded;
1607 assert(blob->pbData);
1608 memcpy(blob->pbData, pbEncoded, blob->cbData);
1614 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1615 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1616 void *pvStructInfo, DWORD *pcbStructInfo)
1618 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
1619 (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
1620 struct AsnDecodeSequenceItem items[] = {
1621 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1622 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1623 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1624 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1625 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1626 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1629 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1630 pvStructInfo, *pcbStructInfo);
1632 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1633 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1634 pvStructInfo, pcbStructInfo,
1635 typeValue ? typeValue->pszObjId : NULL);
1638 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1639 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1640 void *pvStructInfo, DWORD *pcbStructInfo)
1642 CRYPT_ALGORITHM_IDENTIFIER *algo =
1643 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1645 struct AsnDecodeSequenceItem items[] = {
1646 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1647 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1648 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1649 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1650 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1651 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1654 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1655 pvStructInfo, *pcbStructInfo);
1657 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1658 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1659 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1660 if (ret && pvStructInfo)
1662 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1663 debugstr_a(algo->pszObjId));
1668 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
1669 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1670 void *pvStructInfo, DWORD *pcbStructInfo)
1672 struct SPCDigest *digest =
1673 (struct SPCDigest *)pvStructInfo;
1674 struct AsnDecodeSequenceItem items[] = {
1675 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
1676 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1678 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
1679 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
1680 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
1681 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
1684 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1685 pvStructInfo, *pcbStructInfo);
1687 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1688 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1689 pvStructInfo, pcbStructInfo,
1690 digest ? digest->DigestAlgorithm.pszObjId : NULL);
1693 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
1694 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1695 void *pvStructInfo, DWORD *pcbStructInfo)
1699 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1700 pvStructInfo, *pcbStructInfo);
1704 struct AsnDecodeSequenceItem items[] = {
1705 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
1706 CRYPT_AsnDecodeAttributeTypeValue,
1707 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
1708 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
1709 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
1710 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
1712 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
1715 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1716 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1717 pvStructInfo, pcbStructInfo, NULL);
1721 SetLastError(STATUS_ACCESS_VIOLATION);
1724 TRACE("returning %d\n", ret);
1728 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
1729 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1730 void *pvStructInfo, DWORD *pcbStructInfo)
1732 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1733 pvStructInfo, *pcbStructInfo);