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