1 /* wintrust asn functions
3 * Copyright 2007 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
36 #include "wine/exception.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
40 #ifdef WORDS_BIGENDIAN
47 #define hton16(x) RtlUshortByteSwap(x)
48 #define n16toh(x) RtlUshortByteSwap(x)
52 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
53 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
54 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
56 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
58 DWORD bytesNeeded
, significantBytes
= 0;
66 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
67 temp
<<= 8, significantBytes
--)
69 bytesNeeded
= significantBytes
+ 1;
73 *pcbEncoded
= bytesNeeded
;
76 if (*pcbEncoded
< bytesNeeded
)
78 SetLastError(ERROR_MORE_DATA
);
82 *pbEncoded
= (BYTE
)len
;
87 *pbEncoded
++ = significantBytes
| 0x80;
88 for (i
= 0; i
< significantBytes
; i
++)
90 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
94 *pcbEncoded
= bytesNeeded
;
98 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
99 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
103 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
104 DWORD bytesNeeded
, lenBytes
;
106 TRACE("(%d, %p), %p, %d\n", blob
->cbData
, blob
->pbData
, pbEncoded
,
109 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
110 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
112 *pcbEncoded
= bytesNeeded
;
113 else if (*pcbEncoded
< bytesNeeded
)
115 *pcbEncoded
= bytesNeeded
;
116 SetLastError(ERROR_MORE_DATA
);
121 *pbEncoded
++ = ASN_OCTETSTRING
;
122 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
123 pbEncoded
+= lenBytes
;
125 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
127 TRACE("returning %d\n", ret
);
131 BOOL WINAPI
WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType
,
132 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
137 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
138 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
143 const SPC_LINK
*link
= (const SPC_LINK
*)pvStructInfo
;
144 DWORD bytesNeeded
, lenBytes
;
146 switch (link
->dwLinkChoice
)
148 case SPC_FILE_LINK_CHOICE
:
150 DWORD fileNameLen
, fileNameLenBytes
;
153 fileNameLen
= link
->u
.pwszFile
?
154 lstrlenW(link
->u
.pwszFile
) * sizeof(WCHAR
) : 0;
155 CRYPT_EncodeLen(fileNameLen
, NULL
, &fileNameLenBytes
);
156 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, NULL
,
158 bytesNeeded
= 2 + lenBytes
+ fileNameLenBytes
+ fileNameLen
;
161 *pcbEncoded
= bytesNeeded
;
164 else if (*pcbEncoded
< bytesNeeded
)
166 SetLastError(ERROR_MORE_DATA
);
167 *pcbEncoded
= bytesNeeded
;
171 *pcbEncoded
= bytesNeeded
;
172 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2;
173 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, pbEncoded
,
175 pbEncoded
+= lenBytes
;
176 *pbEncoded
++ = ASN_CONTEXT
;
177 CRYPT_EncodeLen(fileNameLen
, pbEncoded
, &fileNameLenBytes
);
178 pbEncoded
+= fileNameLenBytes
;
179 for (ptr
= link
->u
.pwszFile
; ptr
&& *ptr
; ptr
++)
181 *(WCHAR
*)pbEncoded
= hton16(*ptr
);
182 pbEncoded
+= sizeof(WCHAR
);
188 case SPC_MONIKER_LINK_CHOICE
:
190 DWORD classIdLenBytes
, dataLenBytes
, dataLen
;
191 CRYPT_DATA_BLOB classId
= { sizeof(link
->u
.Moniker
.ClassId
),
192 (BYTE
*)link
->u
.Moniker
.ClassId
};
194 CRYPT_EncodeLen(classId
.cbData
, NULL
, &classIdLenBytes
);
195 CRYPT_EncodeLen(link
->u
.Moniker
.SerializedData
.cbData
, NULL
,
197 dataLen
= 2 + classIdLenBytes
+ classId
.cbData
+
198 dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
199 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
200 bytesNeeded
= 1 + dataLen
+ lenBytes
;
203 *pcbEncoded
= bytesNeeded
;
206 else if (*pcbEncoded
< bytesNeeded
)
208 SetLastError(ERROR_MORE_DATA
);
209 *pcbEncoded
= bytesNeeded
;
215 *pcbEncoded
= bytesNeeded
;
216 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
217 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
218 pbEncoded
+= lenBytes
;
219 size
= 1 + classIdLenBytes
+ classId
.cbData
;
220 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
, &classId
,
223 size
= 1 + dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
224 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
,
225 &link
->u
.Moniker
.SerializedData
, pbEncoded
, &size
);
231 case SPC_URL_LINK_CHOICE
:
236 /* Check for invalid characters in URL */
239 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
&& ret
; ptr
++)
243 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
250 CRYPT_EncodeLen(urlLen
, NULL
, &lenBytes
);
251 bytesNeeded
= 1 + lenBytes
+ urlLen
;
253 *pcbEncoded
= bytesNeeded
;
254 else if (*pcbEncoded
< bytesNeeded
)
256 SetLastError(ERROR_MORE_DATA
);
257 *pcbEncoded
= bytesNeeded
;
262 *pcbEncoded
= bytesNeeded
;
263 *pbEncoded
++ = ASN_CONTEXT
;
264 CRYPT_EncodeLen(urlLen
, pbEncoded
, &lenBytes
);
265 pbEncoded
+= lenBytes
;
266 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
; ptr
++)
267 *pbEncoded
++ = (BYTE
)*ptr
;
273 SetLastError(E_INVALIDARG
);
278 SetLastError(STATUS_ACCESS_VIOLATION
);
281 TRACE("returning %d\n", ret
);
285 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
288 struct AsnEncodeSequenceItem
290 const void *pvStructInfo
;
291 CryptEncodeObjectFunc encodeFunc
;
292 DWORD size
; /* used during encoding, not for your use */
295 static BOOL
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
296 struct AsnEncodeSequenceItem items
[], DWORD cItem
, BYTE
*pbEncoded
,
300 DWORD i
, dataLen
= 0;
302 TRACE("%p, %d, %p, %d\n", items
, cItem
, pbEncoded
, *pcbEncoded
);
303 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
305 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
306 items
[i
].pvStructInfo
, NULL
, &items
[i
].size
);
307 /* Some functions propagate their errors through the size */
309 *pcbEncoded
= items
[i
].size
;
310 dataLen
+= items
[i
].size
;
314 DWORD lenBytes
, bytesNeeded
;
316 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
317 bytesNeeded
= 1 + lenBytes
+ dataLen
;
319 *pcbEncoded
= bytesNeeded
;
320 else if (*pcbEncoded
< bytesNeeded
)
322 *pcbEncoded
= bytesNeeded
;
323 SetLastError(ERROR_MORE_DATA
);
328 *pcbEncoded
= bytesNeeded
;
329 *pbEncoded
++ = ASN_SEQUENCE
;
330 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
331 pbEncoded
+= lenBytes
;
332 for (i
= 0; ret
&& i
< cItem
; i
++)
334 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
335 items
[i
].pvStructInfo
, pbEncoded
, &items
[i
].size
);
336 /* Some functions propagate their errors through the size */
338 *pcbEncoded
= items
[i
].size
;
339 pbEncoded
+= items
[i
].size
;
343 TRACE("returning %d\n", ret
);
347 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
348 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
355 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
356 DWORD bytesNeeded
, lenBytes
, dataBytes
;
359 /* yep, MS allows cUnusedBits to be >= 8 */
360 if (!blob
->cUnusedBits
)
362 dataBytes
= blob
->cbData
;
365 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
367 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
368 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
376 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
377 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
380 *pcbEncoded
= bytesNeeded
;
383 else if (*pcbEncoded
< bytesNeeded
)
385 *pcbEncoded
= bytesNeeded
;
386 SetLastError(ERROR_MORE_DATA
);
391 *pcbEncoded
= bytesNeeded
;
392 *pbEncoded
++ = ASN_BITSTRING
;
393 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
394 pbEncoded
+= lenBytes
;
395 *pbEncoded
++ = unusedBits
;
398 BYTE mask
= 0xff << unusedBits
;
402 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
403 pbEncoded
+= dataBytes
- 1;
405 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
411 SetLastError(STATUS_ACCESS_VIOLATION
);
417 struct AsnConstructedItem
420 const void *pvStructInfo
;
421 CryptEncodeObjectFunc encodeFunc
;
424 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
425 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
429 const struct AsnConstructedItem
*item
=
430 (const struct AsnConstructedItem
*)pvStructInfo
;
433 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
434 item
->pvStructInfo
, NULL
, &len
)))
436 DWORD dataLen
, bytesNeeded
;
438 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
439 bytesNeeded
= 1 + dataLen
+ len
;
441 *pcbEncoded
= bytesNeeded
;
442 else if (*pcbEncoded
< bytesNeeded
)
444 *pcbEncoded
= bytesNeeded
;
445 SetLastError(ERROR_MORE_DATA
);
450 *pcbEncoded
= bytesNeeded
;
451 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
452 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
453 pbEncoded
+= dataLen
;
454 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
455 item
->pvStructInfo
, pbEncoded
, &len
);
458 /* Some functions propagate their errors through the size */
465 /* Some functions propagate their errors through the size */
472 BOOL WINAPI
WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType
,
473 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
476 const SPC_PE_IMAGE_DATA
*imageData
=
477 (const SPC_PE_IMAGE_DATA
*)pvStructInfo
;
480 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
481 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
486 struct AsnEncodeSequenceItem items
[2] = {
489 struct AsnConstructedItem constructed
= { 0, imageData
->pFile
,
490 WVTAsn1SpcLinkEncode
};
493 if (imageData
->Flags
.cbData
)
495 items
[cItem
].pvStructInfo
= &imageData
->Flags
;
496 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBits
;
499 if (imageData
->pFile
)
501 items
[cItem
].pvStructInfo
= &constructed
;
502 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
506 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
507 pbEncoded
, pcbEncoded
);
511 SetLastError(STATUS_ACCESS_VIOLATION
);
514 TRACE("returning %d\n", ret
);
518 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
519 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
522 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
523 DWORD bytesNeeded
= 0, lenBytes
;
528 TRACE("%s\n", debugstr_a(pszObjId
));
535 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
537 SetLastError(CRYPT_E_ASN1_ERROR
);
541 firstByte
= val1
* 40 + val2
;
542 ptr
= pszObjId
+ firstPos
;
547 /* note I assume each component is at most 32-bits long in base 2 */
548 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
550 if (val1
>= 0x10000000)
552 else if (val1
>= 0x200000)
554 else if (val1
>= 0x4000)
556 else if (val1
>= 0x80)
566 SetLastError(CRYPT_E_ASN1_ERROR
);
570 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
574 bytesNeeded
+= 1 + lenBytes
;
577 if (*pcbEncoded
< bytesNeeded
)
579 SetLastError(ERROR_MORE_DATA
);
584 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
585 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
586 pbEncoded
+= lenBytes
;
592 *pbEncoded
++ = firstByte
;
593 ptr
= pszObjId
+ firstPos
;
596 sscanf(ptr
, "%d%n", &val
, &pos
);
598 unsigned char outBytes
[5];
601 if (val
>= 0x10000000)
603 else if (val
>= 0x200000)
605 else if (val
>= 0x4000)
607 else if (val
>= 0x80)
611 for (i
= numBytes
; i
> 0; i
--)
613 outBytes
[i
- 1] = val
& 0x7f;
616 for (i
= 0; i
< numBytes
- 1; i
++)
617 *pbEncoded
++ = outBytes
[i
] | 0x80;
618 *pbEncoded
++ = outBytes
[i
];
627 *pcbEncoded
= bytesNeeded
;
631 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
632 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
635 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
639 *pcbEncoded
= blob
->cbData
;
640 else if (*pcbEncoded
< blob
->cbData
)
642 *pcbEncoded
= blob
->cbData
;
643 SetLastError(ERROR_MORE_DATA
);
649 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
650 *pcbEncoded
= blob
->cbData
;
655 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
656 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
657 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
659 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
660 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
661 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
662 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
665 struct AsnEncodeSequenceItem items
[2] = {
666 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
667 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
670 if (algo
->Parameters
.cbData
)
671 items
[1].pvStructInfo
= &algo
->Parameters
;
673 items
[1].pvStructInfo
= &nullBlob
;
674 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
675 sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
679 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
680 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
683 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
=
684 (const CRYPT_ATTRIBUTE_TYPE_VALUE
*)pvStructInfo
;
685 struct AsnEncodeSequenceItem items
[] = {
686 { &typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
687 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
690 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
691 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
696 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
697 CRYPT_HASH_BLOB Digest
;
700 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
701 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
704 const struct SPCDigest
*digest
= (const struct SPCDigest
*)pvStructInfo
;
705 struct AsnEncodeSequenceItem items
[] = {
706 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
707 { &digest
->Digest
, CRYPT_CopyEncodedBlob
, 0 },
710 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
711 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
714 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
715 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
720 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
721 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
725 const SPC_INDIRECT_DATA_CONTENT
*data
=
726 (const SPC_INDIRECT_DATA_CONTENT
*)pvStructInfo
;
727 struct AsnEncodeSequenceItem items
[] = {
728 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
729 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
732 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
733 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
737 SetLastError(STATUS_ACCESS_VIOLATION
);
743 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
744 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
748 LPCWSTR str
= (LPCWSTR
)pvStructInfo
;
749 DWORD bytesNeeded
, lenBytes
, strLen
;
752 strLen
= lstrlenW(str
);
755 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
756 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
758 *pcbEncoded
= bytesNeeded
;
759 else if (*pcbEncoded
< bytesNeeded
)
761 *pcbEncoded
= bytesNeeded
;
762 SetLastError(ERROR_MORE_DATA
);
769 *pcbEncoded
= bytesNeeded
;
770 *pbEncoded
++ = ASN_BMPSTRING
;
771 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
772 pbEncoded
+= lenBytes
;
773 for (i
= 0; i
< strLen
; i
++)
775 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
776 *pbEncoded
++ = str
[i
] & 0x00ff;
782 struct AsnEncodeTagSwappedItem
785 const void *pvStructInfo
;
786 CryptEncodeObjectFunc encodeFunc
;
789 /* Sort of a wacky hack, it encodes something using the struct
790 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
791 * given in the struct AsnEncodeTagSwappedItem.
793 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
794 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
798 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
800 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
801 item
->pvStructInfo
, pbEncoded
, pcbEncoded
);
802 if (ret
&& pbEncoded
)
803 *pbEncoded
= item
->tag
;
807 BOOL WINAPI
WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType
,
808 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
813 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
814 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
818 const SPC_SP_OPUS_INFO
*info
= pvStructInfo
;
820 if (info
->pMoreInfo
&&
821 info
->pMoreInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
822 info
->pMoreInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
823 info
->pMoreInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
824 SetLastError(E_INVALIDARG
);
825 else if (info
->pPublisherInfo
&&
826 info
->pPublisherInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
827 info
->pPublisherInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
828 info
->pPublisherInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
829 SetLastError(E_INVALIDARG
);
832 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
833 struct AsnConstructedItem constructed
[3] = { { 0 } };
834 struct AsnEncodeTagSwappedItem swapped
;
835 DWORD cItem
= 0, cConstructed
= 0;
837 if (info
->pwszProgramName
)
839 swapped
.tag
= ASN_CONTEXT
;
840 swapped
.pvStructInfo
= info
->pwszProgramName
;
841 swapped
.encodeFunc
= CRYPT_AsnEncodeBMPString
;
842 constructed
[cConstructed
].tag
= 0;
843 constructed
[cConstructed
].pvStructInfo
= &swapped
;
844 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
845 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
846 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
852 constructed
[cConstructed
].tag
= 1;
853 constructed
[cConstructed
].pvStructInfo
= info
->pMoreInfo
;
854 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
855 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
856 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
860 if (info
->pPublisherInfo
)
862 constructed
[cConstructed
].tag
= 2;
863 constructed
[cConstructed
].pvStructInfo
= info
->pPublisherInfo
;
864 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
865 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
866 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
870 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
871 items
, cItem
, pbEncoded
, pcbEncoded
);
876 SetLastError(STATUS_ACCESS_VIOLATION
);
882 static BOOL
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
883 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
890 DWORD significantBytes
, lenBytes
, bytesNeeded
;
893 const CRYPT_INTEGER_BLOB
*blob
=
894 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
896 significantBytes
= blob
->cbData
;
897 if (significantBytes
)
899 if (blob
->pbData
[significantBytes
- 1] & 0x80)
901 /* negative, lop off leading (little-endian) 0xffs */
902 for (; significantBytes
> 0 &&
903 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
905 if (blob
->pbData
[significantBytes
- 1] < 0x80)
913 /* positive, lop off leading (little-endian) zeroes */
914 for (; significantBytes
> 0 &&
915 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
917 if (significantBytes
== 0)
918 significantBytes
= 1;
919 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
927 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
929 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
930 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
935 *pcbEncoded
= bytesNeeded
;
938 else if (*pcbEncoded
< bytesNeeded
)
940 *pcbEncoded
= bytesNeeded
;
941 SetLastError(ERROR_MORE_DATA
);
946 *pcbEncoded
= bytesNeeded
;
947 *pbEncoded
++ = ASN_INTEGER
;
950 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
951 pbEncoded
+= lenBytes
;
952 *pbEncoded
++ = padByte
;
956 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
957 pbEncoded
+= lenBytes
;
959 for (; significantBytes
> 0; significantBytes
--)
960 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
966 SetLastError(STATUS_ACCESS_VIOLATION
);
973 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
974 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
977 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
979 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
980 &blob
, pbEncoded
, pcbEncoded
);
983 BOOL WINAPI
WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType
,
984 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
989 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
990 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
994 const CAT_MEMBERINFO
*info
= (const CAT_MEMBERINFO
*)pvStructInfo
;
995 struct AsnEncodeSequenceItem items
[] = {
996 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
997 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
1000 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1001 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1005 SetLastError(STATUS_ACCESS_VIOLATION
);
1011 BOOL WINAPI
WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType
,
1012 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1017 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1018 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1022 const CAT_NAMEVALUE
*value
= (const CAT_NAMEVALUE
*)pvStructInfo
;
1023 struct AsnEncodeSequenceItem items
[] = {
1024 { value
->pwszTag
, CRYPT_AsnEncodeBMPString
, 0 },
1025 { &value
->fdwFlags
, CRYPT_AsnEncodeInt
, 0 },
1026 { &value
->Value
, CRYPT_AsnEncodeOctets
, 0 },
1029 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1030 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1034 SetLastError(STATUS_ACCESS_VIOLATION
);
1040 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1041 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1044 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1053 else if (*pcbEncoded
< 3)
1056 SetLastError(ERROR_MORE_DATA
);
1062 *pbEncoded
++ = ASN_BOOL
;
1064 *pbEncoded
++ = val
? 0xff : 0;
1067 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1071 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType
,
1072 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1077 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1078 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1082 const SPC_FINANCIAL_CRITERIA
*criteria
= pvStructInfo
;
1083 struct AsnEncodeSequenceItem items
[] = {
1084 { &criteria
->fFinancialInfoAvailable
, CRYPT_AsnEncodeBool
, 0 },
1085 { &criteria
->fMeetsCriteria
, CRYPT_AsnEncodeBool
, 0 },
1088 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1089 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1093 SetLastError(STATUS_ACCESS_VIOLATION
);
1099 /* Gets the number of length bytes from the given (leading) length byte */
1100 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1102 /* Helper function to get the encoded length of the data starting at pbEncoded,
1103 * where pbEncoded[0] is the tag. If the data are too short to contain a
1104 * length or if the length is too large for cbEncoded, sets an appropriate
1105 * error code and returns FALSE.
1107 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
1113 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1116 else if (pbEncoded
[1] <= 0x7f)
1118 if (pbEncoded
[1] + 1 > cbEncoded
)
1120 SetLastError(CRYPT_E_ASN1_EOD
);
1125 *len
= pbEncoded
[1];
1129 else if (pbEncoded
[1] == 0x80)
1131 FIXME("unimplemented for indefinite-length encoding\n");
1132 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1137 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
1139 if (lenLen
> sizeof(DWORD
) + 1)
1141 SetLastError(CRYPT_E_ASN1_LARGE
);
1144 else if (lenLen
+ 2 > cbEncoded
)
1146 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1157 out
|= *pbEncoded
++;
1159 if (out
+ lenLen
+ 1 > cbEncoded
)
1161 SetLastError(CRYPT_E_ASN1_EOD
);
1174 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
1175 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1176 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1179 DWORD bytesNeeded
, dataLen
;
1181 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1182 pvStructInfo
, *pcbStructInfo
);
1186 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1189 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
1191 SetLastError(CRYPT_E_ASN1_BADTAG
);
1194 else if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1196 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1197 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
1199 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
1201 *pcbStructInfo
= bytesNeeded
;
1202 else if (*pcbStructInfo
< bytesNeeded
)
1204 SetLastError(ERROR_MORE_DATA
);
1205 *pcbStructInfo
= bytesNeeded
;
1210 CRYPT_DATA_BLOB
*blob
;
1211 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1213 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
1214 blob
->cbData
= dataLen
;
1215 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1216 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
1219 assert(blob
->pbData
);
1221 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
1229 static BOOL
CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType
,
1230 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1231 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1234 DWORD bytesNeeded
= sizeof(SPC_LINK
), dataLen
;
1236 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1237 pvStructInfo
, *pcbStructInfo
);
1239 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1241 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1244 switch (pbEncoded
[0])
1247 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
1249 *pcbStructInfo
= bytesNeeded
;
1250 else if (*pcbStructInfo
< bytesNeeded
)
1252 *pcbStructInfo
= bytesNeeded
;
1253 SetLastError(ERROR_MORE_DATA
);
1258 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1261 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1262 for (i
= 0; i
< dataLen
; i
++)
1263 link
->u
.pwszUrl
[i
] =
1264 *(pbEncoded
+ 1 + lenBytes
+ i
);
1265 link
->u
.pwszUrl
[i
] = '\0';
1266 TRACE("returning url %s\n", debugstr_w(link
->u
.pwszUrl
));
1269 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1:
1271 CRYPT_DATA_BLOB classId
;
1272 DWORD size
= sizeof(classId
);
1274 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1275 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
1276 CRYPT_DECODE_NOCOPY_FLAG
, &classId
, &size
)))
1278 if (classId
.cbData
!= sizeof(SPC_UUID
))
1280 SetLastError(CRYPT_E_BAD_ENCODE
);
1285 CRYPT_DATA_BLOB data
;
1287 /* The tag length for the classId must be 1 since the
1288 * length is correct.
1290 size
= sizeof(data
);
1291 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1292 pbEncoded
+ 3 + lenBytes
+ classId
.cbData
,
1293 cbEncoded
- 3 - lenBytes
- classId
.cbData
,
1294 CRYPT_DECODE_NOCOPY_FLAG
, &data
, &size
)))
1296 bytesNeeded
+= data
.cbData
;
1298 *pcbStructInfo
= bytesNeeded
;
1299 else if (*pcbStructInfo
< bytesNeeded
)
1301 *pcbStructInfo
= bytesNeeded
;
1302 SetLastError(ERROR_MORE_DATA
);
1307 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1309 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1310 /* pwszFile pointer was set by caller, copy it
1311 * before overwriting it
1313 link
->u
.Moniker
.SerializedData
.pbData
=
1314 (BYTE
*)link
->u
.pwszFile
;
1315 memcpy(link
->u
.Moniker
.ClassId
, classId
.pbData
,
1317 memcpy(link
->u
.Moniker
.SerializedData
.pbData
,
1318 data
.pbData
, data
.cbData
);
1319 link
->u
.Moniker
.SerializedData
.cbData
= data
.cbData
;
1326 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2:
1327 if (dataLen
&& pbEncoded
[1 + lenBytes
] != ASN_CONTEXT
)
1328 SetLastError(CRYPT_E_ASN1_BADTAG
);
1329 else if ((ret
= CRYPT_GetLen(pbEncoded
+ 1 + lenBytes
, dataLen
,
1332 BYTE realLenBytes
= GET_LEN_BYTES(pbEncoded
[2 + lenBytes
]);
1334 bytesNeeded
+= realDataLen
+ sizeof(WCHAR
);
1336 *pcbStructInfo
= bytesNeeded
;
1337 else if (*pcbStructInfo
< bytesNeeded
)
1339 *pcbStructInfo
= bytesNeeded
;
1340 SetLastError(ERROR_MORE_DATA
);
1345 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1347 const BYTE
*ptr
= pbEncoded
+ 2 + lenBytes
+ realLenBytes
;
1349 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1350 for (i
= 0; i
< dataLen
/ sizeof(WCHAR
); i
++)
1351 link
->u
.pwszFile
[i
] =
1352 hton16(*(WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1353 link
->u
.pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1354 TRACE("returning file %s\n", debugstr_w(link
->u
.pwszFile
));
1359 bytesNeeded
+= sizeof(WCHAR
);
1361 *pcbStructInfo
= bytesNeeded
;
1362 else if (*pcbStructInfo
< bytesNeeded
)
1364 *pcbStructInfo
= bytesNeeded
;
1365 SetLastError(ERROR_MORE_DATA
);
1370 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1372 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1373 link
->u
.pwszFile
[0] = '\0';
1379 SetLastError(CRYPT_E_ASN1_BADTAG
);
1382 TRACE("returning %d\n", ret
);
1386 BOOL WINAPI
WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType
,
1387 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1388 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1392 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1393 pvStructInfo
, *pcbStructInfo
);
1399 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1400 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, NULL
, &bytesNeeded
);
1404 *pcbStructInfo
= bytesNeeded
;
1405 else if (*pcbStructInfo
< bytesNeeded
)
1407 *pcbStructInfo
= bytesNeeded
;
1408 SetLastError(ERROR_MORE_DATA
);
1413 SPC_LINK
*link
= (SPC_LINK
*)pvStructInfo
;
1416 (LPWSTR
)((BYTE
*)pvStructInfo
+ sizeof(SPC_LINK
));
1417 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1418 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1425 SetLastError(STATUS_ACCESS_VIOLATION
);
1428 TRACE("returning %d\n", ret
);
1432 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1433 DWORD
, DWORD
, void *, DWORD
*);
1436 * The expected tag of the item. If tag is 0, decodeFunc is called
1437 * regardless of the tag value seen.
1439 * A sequence is decoded into a struct. The offset member is the
1440 * offset of this item within that struct.
1442 * The decoder function to use. If this is NULL, then the member isn't
1443 * decoded, but minSize space is reserved for it.
1445 * The minimum amount of space occupied after decoding. You must set this.
1447 * If true, and the tag doesn't match the expected tag for this item,
1448 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1449 * filled with 0 for this member.
1450 * hasPointer, pointerOffset:
1451 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1452 * the offset within the struct of the data pointer (or to the
1453 * first data pointer, if more than one exist).
1455 * Used by CRYPT_AsnDecodeSequence, not for your use.
1457 struct AsnDecodeSequenceItem
1461 CryptDecodeObjectFunc decodeFunc
;
1465 DWORD pointerOffset
;
1469 /* Decodes the items in a sequence, where the items are described in items,
1470 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1471 * pvStructInfo. nextData is a pointer to the memory location at which the
1472 * first decoded item with a dynamic pointer should point.
1473 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1475 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
1476 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1477 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
1481 DWORD i
, decoded
= 0;
1482 const BYTE
*ptr
= pbEncoded
;
1484 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
1485 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
1487 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
1489 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
1493 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
1496 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
1498 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
1500 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
1502 TRACE("Setting next pointer to %p\n",
1504 *(BYTE
**)((BYTE
*)pvStructInfo
+
1505 items
[i
].pointerOffset
) = nextData
;
1507 if (items
[i
].decodeFunc
)
1510 TRACE("decoding item %d\n", i
);
1512 TRACE("sizing item %d\n", i
);
1513 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
1514 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
1515 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
1516 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
1517 : NULL
, &items
[i
].size
);
1520 /* Account for alignment padding */
1521 if (items
[i
].size
% sizeof(DWORD
))
1522 items
[i
].size
+= sizeof(DWORD
) -
1523 items
[i
].size
% sizeof(DWORD
);
1524 TRACE("item %d size: %d\n", i
, items
[i
].size
);
1525 if (nextData
&& items
[i
].hasPointer
&&
1526 items
[i
].size
> items
[i
].minSize
)
1527 nextData
+= items
[i
].size
- items
[i
].minSize
;
1528 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1529 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1530 TRACE("item %d: decoded %d bytes\n", i
,
1531 1 + nextItemLenBytes
+ nextItemLen
);
1533 else if (items
[i
].optional
&&
1534 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1536 TRACE("skipping optional item %d\n", i
);
1537 items
[i
].size
= items
[i
].minSize
;
1538 SetLastError(NOERROR
);
1542 TRACE("item %d failed: %08x\n", i
,
1547 TRACE("item %d: decoded %d bytes\n", i
,
1548 1 + nextItemLenBytes
+ nextItemLen
);
1549 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1550 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1551 items
[i
].size
= items
[i
].minSize
;
1554 else if (items
[i
].optional
)
1556 TRACE("skipping optional item %d\n", i
);
1557 items
[i
].size
= items
[i
].minSize
;
1561 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1562 i
, ptr
[0], items
[i
].tag
);
1563 SetLastError(CRYPT_E_ASN1_BADTAG
);
1568 else if (items
[i
].optional
)
1570 TRACE("missing optional item %d, skipping\n", i
);
1571 items
[i
].size
= items
[i
].minSize
;
1575 TRACE("not enough bytes for item %d, failing\n", i
);
1576 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1581 *cbDecoded
= decoded
;
1582 TRACE("returning %d\n", ret
);
1586 /* This decodes an arbitrary sequence into a contiguous block of memory
1587 * (basically, a struct.) Each element being decoded is described by a struct
1588 * AsnDecodeSequenceItem, see above.
1589 * startingPointer is an optional pointer to the first place where dynamic
1590 * data will be stored. If you know the starting offset, you may pass it
1591 * here. Otherwise, pass NULL, and one will be inferred from the items.
1593 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1594 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1595 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1596 void *startingPointer
)
1600 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items
, cItem
, pbEncoded
,
1601 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1603 if (pbEncoded
[0] == ASN_SEQUENCE
)
1607 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1609 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1610 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1612 cbEncoded
-= 1 + lenBytes
;
1613 if (cbEncoded
< dataLen
)
1615 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
1617 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1621 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1622 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1623 if (ret
&& cbDecoded
!= dataLen
)
1625 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
1627 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1632 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1634 for (i
= 0; i
< cItem
; i
++)
1636 bytesNeeded
+= items
[i
].size
;
1637 structSize
+= items
[i
].minSize
;
1640 *pcbStructInfo
= bytesNeeded
;
1641 else if (*pcbStructInfo
< bytesNeeded
)
1643 SetLastError(ERROR_MORE_DATA
);
1644 *pcbStructInfo
= bytesNeeded
;
1651 *pcbStructInfo
= bytesNeeded
;
1652 if (startingPointer
)
1653 nextData
= (BYTE
*)startingPointer
;
1655 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1656 memset(pvStructInfo
, 0, structSize
);
1657 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1658 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1666 SetLastError(CRYPT_E_ASN1_BADTAG
);
1669 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1673 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1674 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1675 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1679 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
1680 pvStructInfo
, *pcbStructInfo
);
1682 if (pbEncoded
[0] == ASN_BITSTRING
)
1684 DWORD bytesNeeded
, dataLen
;
1686 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1688 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1689 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1691 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1693 *pcbStructInfo
= bytesNeeded
;
1694 else if (*pcbStructInfo
< bytesNeeded
)
1696 *pcbStructInfo
= bytesNeeded
;
1697 SetLastError(ERROR_MORE_DATA
);
1702 CRYPT_BIT_BLOB
*blob
;
1704 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
1705 blob
->cbData
= dataLen
- 1;
1706 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1707 GET_LEN_BYTES(pbEncoded
[1]));
1708 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1710 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1711 GET_LEN_BYTES(pbEncoded
[1]);
1715 assert(blob
->pbData
);
1718 BYTE mask
= 0xff << blob
->cUnusedBits
;
1720 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1721 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1722 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1730 SetLastError(CRYPT_E_ASN1_BADTAG
);
1733 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1737 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1738 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1739 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1744 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1746 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1748 SPC_LINK
**pLink
= (SPC_LINK
**)pvStructInfo
;
1750 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1751 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1755 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1756 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1758 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1759 SetLastError(ERROR_MORE_DATA
);
1764 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1765 /* Set imageData's pointer if necessary */
1766 if (size
> sizeof(SPC_LINK
))
1768 (*pLink
)->u
.pwszUrl
=
1769 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1771 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1772 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1773 *pLink
, pcbStructInfo
);
1780 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1781 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1782 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1786 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1787 pvStructInfo
, *pcbStructInfo
);
1791 struct AsnDecodeSequenceItem items
[] = {
1792 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1793 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1794 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1795 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1796 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1797 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1800 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1801 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1802 pvStructInfo
, pcbStructInfo
, NULL
);
1806 SetLastError(STATUS_ACCESS_VIOLATION
);
1809 TRACE("returning %d\n", ret
);
1813 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1814 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1815 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1820 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1821 pvStructInfo
, *pcbStructInfo
);
1823 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1825 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1826 DWORD bytesNeeded
= sizeof(LPSTR
);
1830 /* The largest possible string for the first two components
1831 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1836 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1837 pbEncoded
[1 + lenBytes
] / 40,
1838 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1840 bytesNeeded
+= strlen(firstTwo
) + 1;
1841 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1842 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1844 /* large enough for ".4000000" */
1848 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1855 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1858 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1865 snprintf(str
, sizeof(str
), ".%d", val
);
1866 bytesNeeded
+= strlen(str
);
1871 *pcbStructInfo
= bytesNeeded
;
1872 else if (*pcbStructInfo
< bytesNeeded
)
1874 *pcbStructInfo
= bytesNeeded
;
1875 SetLastError(ERROR_MORE_DATA
);
1883 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1886 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1887 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1889 pszObjId
+= strlen(pszObjId
);
1890 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1891 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1895 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1904 sprintf(pszObjId
, ".%d", val
);
1905 pszObjId
+= strlen(pszObjId
);
1909 *(LPSTR
*)pvStructInfo
= NULL
;
1910 *pcbStructInfo
= bytesNeeded
;
1916 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1917 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1918 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1922 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1923 pvStructInfo
, *pcbStructInfo
);
1926 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1927 else if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1928 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1929 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1931 SetLastError(CRYPT_E_ASN1_BADTAG
);
1935 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1936 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1937 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1940 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1942 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1943 pvStructInfo
, *pcbStructInfo
);
1945 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1946 bytesNeeded
+= cbEncoded
;
1948 *pcbStructInfo
= bytesNeeded
;
1949 else if (*pcbStructInfo
< bytesNeeded
)
1951 SetLastError(ERROR_MORE_DATA
);
1952 *pcbStructInfo
= bytesNeeded
;
1957 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
1959 *pcbStructInfo
= bytesNeeded
;
1960 blob
->cbData
= cbEncoded
;
1961 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1962 blob
->pbData
= (LPBYTE
)pbEncoded
;
1965 assert(blob
->pbData
);
1966 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1972 static BOOL WINAPI
CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType
,
1973 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1974 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1976 CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
=
1977 (CRYPT_ATTRIBUTE_TYPE_VALUE
*)pvStructInfo
;
1978 struct AsnDecodeSequenceItem items
[] = {
1979 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1980 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1981 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1982 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1983 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1984 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1987 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1988 pvStructInfo
, *pcbStructInfo
);
1990 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1991 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1992 pvStructInfo
, pcbStructInfo
,
1993 typeValue
? typeValue
->pszObjId
: NULL
);
1996 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
1997 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1998 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2000 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
2001 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
2003 struct AsnDecodeSequenceItem items
[] = {
2004 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2005 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2006 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2007 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2008 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2009 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2012 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2013 pvStructInfo
, *pcbStructInfo
);
2015 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2016 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2017 pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2018 if (ret
&& pvStructInfo
)
2020 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2021 debugstr_a(algo
->pszObjId
));
2026 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
2027 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2028 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2030 struct SPCDigest
*digest
=
2031 (struct SPCDigest
*)pvStructInfo
;
2032 struct AsnDecodeSequenceItem items
[] = {
2033 { ASN_SEQUENCEOF
, offsetof(struct SPCDigest
, DigestAlgorithm
),
2034 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2036 offsetof(struct SPCDigest
, DigestAlgorithm
.pszObjId
), 0 },
2037 { ASN_OCTETSTRING
, offsetof(struct SPCDigest
, Digest
),
2038 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
),
2039 FALSE
, TRUE
, offsetof(struct SPCDigest
, Digest
.pbData
), 0 },
2042 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2043 pvStructInfo
, *pcbStructInfo
);
2045 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2046 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2047 pvStructInfo
, pcbStructInfo
,
2048 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
2051 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
2052 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2053 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2057 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2058 pvStructInfo
, *pcbStructInfo
);
2062 struct AsnDecodeSequenceItem items
[] = {
2063 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
2064 CRYPT_AsnDecodeAttributeTypeValue
,
2065 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
2066 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
2067 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
2068 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
2070 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
2073 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2074 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2075 pvStructInfo
, pcbStructInfo
, NULL
);
2079 SetLastError(STATUS_ACCESS_VIOLATION
);
2082 TRACE("returning %d\n", ret
);
2086 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
2087 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2088 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2090 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2091 pvStructInfo
, *pcbStructInfo
);
2095 static BOOL WINAPI
CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType
,
2096 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2097 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2100 DWORD bytesNeeded
, dataLen
;
2102 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2104 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2106 bytesNeeded
= dataLen
+ 2 + sizeof(LPWSTR
);
2108 *pcbStructInfo
= bytesNeeded
;
2109 else if (*pcbStructInfo
< bytesNeeded
)
2111 *pcbStructInfo
= bytesNeeded
;
2112 SetLastError(ERROR_MORE_DATA
);
2120 *pcbStructInfo
= bytesNeeded
;
2121 assert(pvStructInfo
);
2122 str
= *(LPWSTR
*)pvStructInfo
;
2123 for (i
= 0; i
< dataLen
/ 2; i
++)
2124 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
2125 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
2126 /* Decoded string is always NULL-terminated */
2133 static BOOL
CRYPT_AsnDecodeInteger(const BYTE
*pbEncoded
,
2134 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2137 DWORD bytesNeeded
, dataLen
;
2139 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2141 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2143 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2145 *pcbStructInfo
= bytesNeeded
;
2146 else if (*pcbStructInfo
< bytesNeeded
)
2148 *pcbStructInfo
= bytesNeeded
;
2149 SetLastError(ERROR_MORE_DATA
);
2154 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2156 *pcbStructInfo
= bytesNeeded
;
2157 blob
->cbData
= dataLen
;
2158 assert(blob
->pbData
);
2163 for (i
= 0; i
< blob
->cbData
; i
++)
2165 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
2174 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2175 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2176 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2177 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2180 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
2181 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
2182 DWORD size
= sizeof(buf
);
2184 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
2185 ret
= CRYPT_AsnDecodeInteger(pbEncoded
, cbEncoded
, 0, buf
, &size
);
2189 *pcbStructInfo
= sizeof(int);
2190 else if (*pcbStructInfo
< sizeof(int))
2192 *pcbStructInfo
= sizeof(int);
2193 SetLastError(ERROR_MORE_DATA
);
2201 *pcbStructInfo
= sizeof(int);
2202 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
2204 /* initialize to a negative value to sign-extend */
2209 for (i
= 0; i
< blob
->cbData
; i
++)
2212 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
2214 memcpy(pvStructInfo
, &val
, sizeof(int));
2217 else if (GetLastError() == ERROR_MORE_DATA
)
2218 SetLastError(CRYPT_E_ASN1_LARGE
);
2222 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
2223 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2224 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2228 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2229 pvStructInfo
, *pcbStructInfo
);
2233 struct AsnDecodeSequenceItem items
[] = {
2234 { ASN_BMPSTRING
, offsetof(CAT_MEMBERINFO
, pwszSubjGuid
),
2235 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2236 offsetof(CAT_MEMBERINFO
, pwszSubjGuid
), 0 },
2237 { ASN_INTEGER
, offsetof(CAT_MEMBERINFO
, dwCertVersion
),
2238 CRYPT_AsnDecodeInt
, sizeof(DWORD
),
2239 FALSE
, FALSE
, 0, 0 },
2242 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2243 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2244 pvStructInfo
, pcbStructInfo
, NULL
);
2248 SetLastError(STATUS_ACCESS_VIOLATION
);
2251 TRACE("returning %d\n", ret
);
2255 BOOL WINAPI
WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType
,
2256 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2257 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2261 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2262 pvStructInfo
, *pcbStructInfo
);
2266 struct AsnDecodeSequenceItem items
[] = {
2267 { ASN_BMPSTRING
, offsetof(CAT_NAMEVALUE
, pwszTag
),
2268 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2269 offsetof(CAT_NAMEVALUE
, pwszTag
), 0 },
2270 { ASN_INTEGER
, offsetof(CAT_NAMEVALUE
, fdwFlags
),
2271 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2272 { ASN_OCTETSTRING
, offsetof(CAT_NAMEVALUE
, Value
),
2273 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2274 offsetof(CAT_NAMEVALUE
, Value
.pbData
), 0 },
2277 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2278 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2279 pvStructInfo
, pcbStructInfo
, NULL
);
2283 SetLastError(STATUS_ACCESS_VIOLATION
);
2286 TRACE("returning %d\n", ret
);
2290 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2291 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2292 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2298 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2301 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2303 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2306 if (pbEncoded
[1] > 1)
2308 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2313 *pcbStructInfo
= sizeof(BOOL
);
2316 else if (*pcbStructInfo
< sizeof(BOOL
))
2318 *pcbStructInfo
= sizeof(BOOL
);
2319 SetLastError(ERROR_MORE_DATA
);
2324 *pcbStructInfo
= sizeof(BOOL
);
2325 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
2328 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2332 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType
,
2333 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2334 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2338 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2339 pvStructInfo
, *pcbStructInfo
);
2343 struct AsnDecodeSequenceItem items
[] = {
2344 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fFinancialInfoAvailable
),
2345 CRYPT_AsnDecodeBool
, sizeof(BOOL
), FALSE
, FALSE
, 0, 0 },
2346 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fMeetsCriteria
),
2347 CRYPT_AsnDecodeBool
, sizeof(BOOL
), FALSE
, FALSE
, 0, 0 },
2350 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2351 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2352 pvStructInfo
, pcbStructInfo
, NULL
);
2356 SetLastError(STATUS_ACCESS_VIOLATION
);
2359 TRACE("returning %d\n", ret
);