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
);