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
32 #include "wine/debug.h"
33 #include "wine/exception.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
37 #ifdef WORDS_BIGENDIAN
44 #define hton16(x) RtlUshortByteSwap(x)
45 #define n16toh(x) RtlUshortByteSwap(x)
49 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
50 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
51 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
53 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
55 DWORD bytesNeeded
, significantBytes
= 0;
63 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
64 temp
<<= 8, significantBytes
--)
66 bytesNeeded
= significantBytes
+ 1;
70 *pcbEncoded
= bytesNeeded
;
73 if (*pcbEncoded
< bytesNeeded
)
75 SetLastError(ERROR_MORE_DATA
);
79 *pbEncoded
= (BYTE
)len
;
84 *pbEncoded
++ = significantBytes
| 0x80;
85 for (i
= 0; i
< significantBytes
; i
++)
87 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
91 *pcbEncoded
= bytesNeeded
;
95 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
96 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
100 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
101 DWORD bytesNeeded
, lenBytes
;
103 TRACE("(%ld, %p), %p, %ld\n", blob
->cbData
, blob
->pbData
, pbEncoded
,
106 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
107 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
109 *pcbEncoded
= bytesNeeded
;
110 else if (*pcbEncoded
< bytesNeeded
)
112 *pcbEncoded
= bytesNeeded
;
113 SetLastError(ERROR_MORE_DATA
);
118 *pbEncoded
++ = ASN_OCTETSTRING
;
119 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
120 pbEncoded
+= lenBytes
;
122 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
124 TRACE("returning %d\n", ret
);
128 BOOL WINAPI
WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType
,
129 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
134 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
135 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
140 const SPC_LINK
*link
= pvStructInfo
;
141 DWORD bytesNeeded
, lenBytes
;
143 switch (link
->dwLinkChoice
)
145 case SPC_FILE_LINK_CHOICE
:
147 DWORD fileNameLen
, fileNameLenBytes
;
150 fileNameLen
= link
->pwszFile
?
151 lstrlenW(link
->pwszFile
) * sizeof(WCHAR
) : 0;
152 CRYPT_EncodeLen(fileNameLen
, NULL
, &fileNameLenBytes
);
153 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, NULL
,
155 bytesNeeded
= 2 + lenBytes
+ fileNameLenBytes
+ fileNameLen
;
158 *pcbEncoded
= bytesNeeded
;
161 else if (*pcbEncoded
< bytesNeeded
)
163 SetLastError(ERROR_MORE_DATA
);
164 *pcbEncoded
= bytesNeeded
;
168 *pcbEncoded
= bytesNeeded
;
169 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2;
170 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, pbEncoded
,
172 pbEncoded
+= lenBytes
;
173 *pbEncoded
++ = ASN_CONTEXT
;
174 CRYPT_EncodeLen(fileNameLen
, pbEncoded
, &fileNameLenBytes
);
175 pbEncoded
+= fileNameLenBytes
;
176 for (ptr
= link
->pwszFile
; ptr
&& *ptr
; ptr
++)
178 *(WCHAR
*)pbEncoded
= hton16(*ptr
);
179 pbEncoded
+= sizeof(WCHAR
);
185 case SPC_MONIKER_LINK_CHOICE
:
187 DWORD classIdLenBytes
, dataLenBytes
, dataLen
;
188 CRYPT_DATA_BLOB classId
= { sizeof(link
->Moniker
.ClassId
),
189 (BYTE
*)link
->Moniker
.ClassId
};
191 CRYPT_EncodeLen(classId
.cbData
, NULL
, &classIdLenBytes
);
192 CRYPT_EncodeLen(link
->Moniker
.SerializedData
.cbData
, NULL
,
194 dataLen
= 2 + classIdLenBytes
+ classId
.cbData
+
195 dataLenBytes
+ link
->Moniker
.SerializedData
.cbData
;
196 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
197 bytesNeeded
= 1 + dataLen
+ lenBytes
;
200 *pcbEncoded
= bytesNeeded
;
203 else if (*pcbEncoded
< bytesNeeded
)
205 SetLastError(ERROR_MORE_DATA
);
206 *pcbEncoded
= bytesNeeded
;
212 *pcbEncoded
= bytesNeeded
;
213 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
214 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
215 pbEncoded
+= lenBytes
;
216 size
= 1 + classIdLenBytes
+ classId
.cbData
;
217 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
, &classId
,
220 size
= 1 + dataLenBytes
+ link
->Moniker
.SerializedData
.cbData
;
221 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
,
222 &link
->Moniker
.SerializedData
, pbEncoded
, &size
);
228 case SPC_URL_LINK_CHOICE
:
233 /* Check for invalid characters in URL */
236 for (ptr
= link
->pwszUrl
; ptr
&& *ptr
&& ret
; ptr
++)
240 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
247 CRYPT_EncodeLen(urlLen
, NULL
, &lenBytes
);
248 bytesNeeded
= 1 + lenBytes
+ urlLen
;
250 *pcbEncoded
= bytesNeeded
;
251 else if (*pcbEncoded
< bytesNeeded
)
253 SetLastError(ERROR_MORE_DATA
);
254 *pcbEncoded
= bytesNeeded
;
259 *pcbEncoded
= bytesNeeded
;
260 *pbEncoded
++ = ASN_CONTEXT
;
261 CRYPT_EncodeLen(urlLen
, pbEncoded
, &lenBytes
);
262 pbEncoded
+= lenBytes
;
263 for (ptr
= link
->pwszUrl
; ptr
&& *ptr
; ptr
++)
264 *pbEncoded
++ = (BYTE
)*ptr
;
270 SetLastError(E_INVALIDARG
);
275 SetLastError(STATUS_ACCESS_VIOLATION
);
278 TRACE("returning %d\n", ret
);
282 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
285 struct AsnEncodeSequenceItem
287 const void *pvStructInfo
;
288 CryptEncodeObjectFunc encodeFunc
;
289 DWORD size
; /* used during encoding, not for your use */
292 static BOOL
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
293 struct AsnEncodeSequenceItem items
[], DWORD cItem
, BYTE
*pbEncoded
,
297 DWORD i
, dataLen
= 0;
299 TRACE("%p, %ld, %p, %ld\n", items
, cItem
, pbEncoded
, *pcbEncoded
);
300 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
302 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
303 items
[i
].pvStructInfo
, NULL
, &items
[i
].size
);
304 /* Some functions propagate their errors through the size */
306 *pcbEncoded
= items
[i
].size
;
307 dataLen
+= items
[i
].size
;
311 DWORD lenBytes
, bytesNeeded
;
313 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
314 bytesNeeded
= 1 + lenBytes
+ dataLen
;
316 *pcbEncoded
= bytesNeeded
;
317 else if (*pcbEncoded
< bytesNeeded
)
319 *pcbEncoded
= bytesNeeded
;
320 SetLastError(ERROR_MORE_DATA
);
325 *pcbEncoded
= bytesNeeded
;
326 *pbEncoded
++ = ASN_SEQUENCE
;
327 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
328 pbEncoded
+= lenBytes
;
329 for (i
= 0; ret
&& i
< cItem
; i
++)
331 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
332 items
[i
].pvStructInfo
, pbEncoded
, &items
[i
].size
);
333 /* Some functions propagate their errors through the size */
335 *pcbEncoded
= items
[i
].size
;
336 pbEncoded
+= items
[i
].size
;
340 TRACE("returning %d\n", ret
);
344 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
345 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
352 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
353 DWORD bytesNeeded
, lenBytes
, dataBytes
;
356 /* yep, MS allows cUnusedBits to be >= 8 */
357 if (!blob
->cUnusedBits
)
359 dataBytes
= blob
->cbData
;
362 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
364 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
365 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
373 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
374 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
377 *pcbEncoded
= bytesNeeded
;
380 else if (*pcbEncoded
< bytesNeeded
)
382 *pcbEncoded
= bytesNeeded
;
383 SetLastError(ERROR_MORE_DATA
);
388 *pcbEncoded
= bytesNeeded
;
389 *pbEncoded
++ = ASN_BITSTRING
;
390 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
391 pbEncoded
+= lenBytes
;
392 *pbEncoded
++ = unusedBits
;
395 BYTE mask
= 0xff << unusedBits
;
399 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
400 pbEncoded
+= dataBytes
- 1;
402 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
408 SetLastError(STATUS_ACCESS_VIOLATION
);
414 struct AsnConstructedItem
417 const void *pvStructInfo
;
418 CryptEncodeObjectFunc encodeFunc
;
421 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
422 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
426 const struct AsnConstructedItem
*item
= pvStructInfo
;
429 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
430 item
->pvStructInfo
, NULL
, &len
)))
432 DWORD dataLen
, bytesNeeded
;
434 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
435 bytesNeeded
= 1 + dataLen
+ len
;
437 *pcbEncoded
= bytesNeeded
;
438 else if (*pcbEncoded
< bytesNeeded
)
440 *pcbEncoded
= bytesNeeded
;
441 SetLastError(ERROR_MORE_DATA
);
446 *pcbEncoded
= bytesNeeded
;
447 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
448 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
449 pbEncoded
+= dataLen
;
450 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
451 item
->pvStructInfo
, pbEncoded
, &len
);
454 /* Some functions propagate their errors through the size */
461 /* Some functions propagate their errors through the size */
468 BOOL WINAPI
WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType
,
469 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
472 const SPC_PE_IMAGE_DATA
*imageData
= pvStructInfo
;
475 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
476 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
481 struct AsnEncodeSequenceItem items
[2] = {
484 struct AsnConstructedItem constructed
= { 0, imageData
->pFile
,
485 WVTAsn1SpcLinkEncode
};
488 if (imageData
->Flags
.cbData
)
490 items
[cItem
].pvStructInfo
= &imageData
->Flags
;
491 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBits
;
494 if (imageData
->pFile
)
496 items
[cItem
].pvStructInfo
= &constructed
;
497 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
501 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
502 pbEncoded
, pcbEncoded
);
506 SetLastError(STATUS_ACCESS_VIOLATION
);
509 TRACE("returning %d\n", ret
);
513 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
514 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
517 LPCSTR pszObjId
= pvStructInfo
;
518 DWORD bytesNeeded
= 0, lenBytes
;
523 TRACE("%s\n", debugstr_a(pszObjId
));
530 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
532 SetLastError(CRYPT_E_ASN1_ERROR
);
536 firstByte
= val1
* 40 + val2
;
537 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
= 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 /* Different from the one in crypt32 */
656 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
657 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
658 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
660 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= 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 },
671 if (algo
->Parameters
.cbData
)
672 items
[1].pvStructInfo
= &algo
->Parameters
;
673 else if (algo
->pszObjId
)
674 items
[1].pvStructInfo
= &nullBlob
;
677 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
678 pbEncoded
, pcbEncoded
);
682 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
683 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
686 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
687 struct AsnEncodeSequenceItem items
[] = {
688 { typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
689 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
692 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
693 pbEncoded
, pcbEncoded
);
698 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
699 CRYPT_HASH_BLOB Digest
;
702 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
703 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
706 const struct SPCDigest
*digest
= pvStructInfo
;
707 struct AsnEncodeSequenceItem items
[] = {
708 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
709 { &digest
->Digest
, CRYPT_AsnEncodeOctets
, 0 },
712 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
713 pbEncoded
, pcbEncoded
);
716 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
717 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
722 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
723 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
727 const SPC_INDIRECT_DATA_CONTENT
*data
= pvStructInfo
;
728 struct AsnEncodeSequenceItem items
[] = {
729 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
730 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
733 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
734 pbEncoded
, pcbEncoded
);
738 SetLastError(STATUS_ACCESS_VIOLATION
);
744 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
745 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
749 LPCWSTR str
= pvStructInfo
;
750 DWORD bytesNeeded
, lenBytes
, strLen
;
753 strLen
= lstrlenW(str
);
756 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
757 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
759 *pcbEncoded
= bytesNeeded
;
760 else if (*pcbEncoded
< bytesNeeded
)
762 *pcbEncoded
= bytesNeeded
;
763 SetLastError(ERROR_MORE_DATA
);
770 *pcbEncoded
= bytesNeeded
;
771 *pbEncoded
++ = ASN_BMPSTRING
;
772 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
773 pbEncoded
+= lenBytes
;
774 for (i
= 0; i
< strLen
; i
++)
776 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
777 *pbEncoded
++ = str
[i
] & 0x00ff;
783 struct AsnEncodeTagSwappedItem
786 const void *pvStructInfo
;
787 CryptEncodeObjectFunc encodeFunc
;
790 /* Sort of a wacky hack, it encodes something using the struct
791 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
792 * given in the struct AsnEncodeTagSwappedItem.
794 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
795 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
799 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
801 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
802 item
->pvStructInfo
, pbEncoded
, pcbEncoded
);
803 if (ret
&& pbEncoded
)
804 *pbEncoded
= item
->tag
;
808 BOOL WINAPI
WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType
,
809 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
814 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
815 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
819 const SPC_SP_OPUS_INFO
*info
= pvStructInfo
;
821 if (info
->pMoreInfo
&&
822 info
->pMoreInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
823 info
->pMoreInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
824 info
->pMoreInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
825 SetLastError(E_INVALIDARG
);
826 else if (info
->pPublisherInfo
&&
827 info
->pPublisherInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
828 info
->pPublisherInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
829 info
->pPublisherInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
830 SetLastError(E_INVALIDARG
);
833 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
834 struct AsnConstructedItem constructed
[3] = { { 0 } };
835 struct AsnEncodeTagSwappedItem swapped
;
836 DWORD cItem
= 0, cConstructed
= 0;
838 if (info
->pwszProgramName
)
840 swapped
.tag
= ASN_CONTEXT
;
841 swapped
.pvStructInfo
= info
->pwszProgramName
;
842 swapped
.encodeFunc
= CRYPT_AsnEncodeBMPString
;
843 constructed
[cConstructed
].tag
= 0;
844 constructed
[cConstructed
].pvStructInfo
= &swapped
;
845 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
846 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
847 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
853 constructed
[cConstructed
].tag
= 1;
854 constructed
[cConstructed
].pvStructInfo
= info
->pMoreInfo
;
855 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
856 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
857 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
861 if (info
->pPublisherInfo
)
863 constructed
[cConstructed
].tag
= 2;
864 constructed
[cConstructed
].pvStructInfo
= info
->pPublisherInfo
;
865 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
866 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
867 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
871 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
872 items
, cItem
, pbEncoded
, pcbEncoded
);
877 SetLastError(STATUS_ACCESS_VIOLATION
);
883 static BOOL
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
884 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
891 DWORD significantBytes
, lenBytes
, bytesNeeded
;
894 const CRYPT_INTEGER_BLOB
*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 static 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%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
990 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
994 const CAT_MEMBERINFO
*info
= pvStructInfo
;
995 struct AsnEncodeSequenceItem items
[] = {
996 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
997 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
1000 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
1001 pbEncoded
, pcbEncoded
);
1005 SetLastError(STATUS_ACCESS_VIOLATION
);
1011 BOOL WINAPI
WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType
,
1012 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1017 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType
,
1018 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1022 const CAT_NAMEVALUE
*value
= 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
, items
, ARRAY_SIZE(items
),
1030 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 (%08lx)\n", ret
, GetLastError());
1071 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType
,
1072 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1077 TRACE("(0x%08lx, %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
, items
, ARRAY_SIZE(items
),
1089 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, %ld, %08lx, %p, %ld\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
= 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, %ld, %08lx, %p, %ld\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
= pvStructInfo
;
1261 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1262 for (i
= 0; i
< dataLen
; i
++)
1264 *(pbEncoded
+ 1 + lenBytes
+ i
);
1265 link
->pwszUrl
[i
] = '\0';
1266 TRACE("returning url %s\n", debugstr_w(link
->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
= pvStructInfo
;
1309 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1310 /* pwszFile pointer was set by caller, copy it
1311 * before overwriting it
1313 link
->Moniker
.SerializedData
.pbData
=
1314 (BYTE
*)link
->pwszFile
;
1315 memcpy(link
->Moniker
.ClassId
, classId
.pbData
,
1317 memcpy(link
->Moniker
.SerializedData
.pbData
,
1318 data
.pbData
, data
.cbData
);
1319 link
->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
= 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
++)
1352 hton16(*(const WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1353 link
->pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1354 TRACE("returning file %s\n", debugstr_w(link
->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
= pvStructInfo
;
1372 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1373 link
->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, %ld, %08lx, %p, %ld\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
= 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 /* Align up to a DWORD_PTR boundary
1471 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1))
1473 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
1474 #define MEMBERSIZE(s, member, nextmember) \
1475 (offsetof(s, nextmember) - offsetof(s, member))
1478 /* Decodes the items in a sequence, where the items are described in items,
1479 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1480 * pvStructInfo. nextData is a pointer to the memory location at which the
1481 * first decoded item with a dynamic pointer should point.
1482 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1484 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
1485 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1486 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
1490 DWORD i
, decoded
= 0;
1491 const BYTE
*ptr
= pbEncoded
;
1493 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %p\n", items
, cItem
, pbEncoded
,
1494 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
1496 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
1498 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
1502 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
1505 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
1507 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
1509 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
1511 TRACE("Setting next pointer to %p\n",
1513 *(BYTE
**)((BYTE
*)pvStructInfo
+
1514 items
[i
].pointerOffset
) = nextData
;
1516 if (items
[i
].decodeFunc
)
1519 TRACE("decoding item %ld\n", i
);
1521 TRACE("sizing item %ld\n", i
);
1522 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
1523 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
1524 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
1525 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
1526 : NULL
, &items
[i
].size
);
1529 if (items
[i
].size
< items
[i
].minSize
)
1530 items
[i
].size
= items
[i
].minSize
;
1531 else if (items
[i
].size
> items
[i
].minSize
)
1533 /* Account for alignment padding */
1534 items
[i
].size
= ALIGN_DWORD_PTR(items
[i
].size
);
1536 TRACE("item %ld size: %ld\n", i
, items
[i
].size
);
1537 if (nextData
&& items
[i
].hasPointer
&&
1538 items
[i
].size
> items
[i
].minSize
)
1539 nextData
+= items
[i
].size
- items
[i
].minSize
;
1540 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1541 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1542 TRACE("item %ld: decoded %ld bytes\n", i
,
1543 1 + nextItemLenBytes
+ nextItemLen
);
1545 else if (items
[i
].optional
&&
1546 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1548 TRACE("skipping optional item %ld\n", i
);
1549 items
[i
].size
= items
[i
].minSize
;
1550 SetLastError(NOERROR
);
1554 TRACE("item %ld failed: %08lx\n", i
,
1559 TRACE("item %ld: decoded %ld bytes\n", i
,
1560 1 + nextItemLenBytes
+ nextItemLen
);
1561 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1562 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1563 items
[i
].size
= items
[i
].minSize
;
1566 else if (items
[i
].optional
)
1568 TRACE("skipping optional item %ld\n", i
);
1569 items
[i
].size
= items
[i
].minSize
;
1573 TRACE("item %ld: tag %02x doesn't match expected %02x\n",
1574 i
, ptr
[0], items
[i
].tag
);
1575 SetLastError(CRYPT_E_ASN1_BADTAG
);
1580 else if (items
[i
].optional
)
1582 TRACE("missing optional item %ld, skipping\n", i
);
1583 items
[i
].size
= items
[i
].minSize
;
1587 TRACE("not enough bytes for item %ld, failing\n", i
);
1588 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1593 *cbDecoded
= decoded
;
1594 TRACE("returning %d\n", ret
);
1598 /* This decodes an arbitrary sequence into a contiguous block of memory
1599 * (basically, a struct.) Each element being decoded is described by a struct
1600 * AsnDecodeSequenceItem, see above.
1601 * startingPointer is an optional pointer to the first place where dynamic
1602 * data will be stored. If you know the starting offset, you may pass it
1603 * here. Otherwise, pass NULL, and one will be inferred from the items.
1605 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1606 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1607 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1608 void *startingPointer
)
1612 TRACE("%p, %ld, %p, %ld, %08lx, %p, %ld, %p\n", items
, cItem
, pbEncoded
,
1613 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1615 if (pbEncoded
[0] == ASN_SEQUENCE
)
1619 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1621 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1622 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1624 cbEncoded
-= 1 + lenBytes
;
1625 if (cbEncoded
< dataLen
)
1627 TRACE("dataLen %ld exceeds cbEncoded %ld, failing\n", dataLen
,
1629 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1633 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1634 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1635 if (ret
&& cbDecoded
!= dataLen
)
1637 TRACE("expected %ld decoded, got %ld, failing\n", dataLen
,
1639 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1644 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1646 for (i
= 0; i
< cItem
; i
++)
1648 bytesNeeded
+= items
[i
].size
;
1649 structSize
+= items
[i
].minSize
;
1652 *pcbStructInfo
= bytesNeeded
;
1653 else if (*pcbStructInfo
< bytesNeeded
)
1655 SetLastError(ERROR_MORE_DATA
);
1656 *pcbStructInfo
= bytesNeeded
;
1663 *pcbStructInfo
= bytesNeeded
;
1664 if (startingPointer
)
1665 nextData
= startingPointer
;
1667 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1668 memset(pvStructInfo
, 0, structSize
);
1669 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1670 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1678 SetLastError(CRYPT_E_ASN1_BADTAG
);
1681 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1685 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1686 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1687 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1691 TRACE("(%p, %ld, 0x%08lx, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
1692 pvStructInfo
, *pcbStructInfo
);
1694 if (pbEncoded
[0] == ASN_BITSTRING
)
1696 DWORD bytesNeeded
, dataLen
;
1698 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1700 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1701 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1703 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1705 *pcbStructInfo
= bytesNeeded
;
1706 else if (*pcbStructInfo
< bytesNeeded
)
1708 *pcbStructInfo
= bytesNeeded
;
1709 SetLastError(ERROR_MORE_DATA
);
1714 CRYPT_BIT_BLOB
*blob
;
1716 blob
= pvStructInfo
;
1717 blob
->cbData
= dataLen
- 1;
1718 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1719 GET_LEN_BYTES(pbEncoded
[1]));
1720 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1722 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1723 GET_LEN_BYTES(pbEncoded
[1]);
1727 assert(blob
->pbData
);
1730 BYTE mask
= 0xff << blob
->cUnusedBits
;
1732 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1733 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1734 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1742 SetLastError(CRYPT_E_ASN1_BADTAG
);
1745 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
1749 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1750 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1751 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1756 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1758 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1760 SPC_LINK
**pLink
= pvStructInfo
;
1762 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1763 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1767 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1768 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1770 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1771 SetLastError(ERROR_MORE_DATA
);
1776 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1777 /* Set imageData's pointer if necessary */
1778 if (size
> sizeof(SPC_LINK
))
1781 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1783 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1784 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1785 *pLink
, pcbStructInfo
);
1792 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1793 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1794 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1798 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
1799 pvStructInfo
, *pcbStructInfo
);
1803 struct AsnDecodeSequenceItem items
[] = {
1804 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1805 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1806 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1807 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1808 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1809 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1812 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
1813 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
1817 SetLastError(STATUS_ACCESS_VIOLATION
);
1820 TRACE("returning %d\n", ret
);
1824 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1825 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1826 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1831 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
1832 pvStructInfo
, *pcbStructInfo
);
1834 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1836 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1837 DWORD bytesNeeded
= sizeof(LPSTR
);
1841 /* The largest possible string for the first two components
1842 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1847 sprintf(firstTwo
, "%d.%d",
1848 pbEncoded
[1 + lenBytes
] / 40,
1849 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1851 bytesNeeded
+= strlen(firstTwo
) + 1;
1852 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1853 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1855 /* large enough for ".4000000" */
1859 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1866 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1869 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1876 snprintf(str
, sizeof(str
), ".%d", val
);
1877 bytesNeeded
+= strlen(str
);
1884 *pcbStructInfo
= bytesNeeded
;
1885 else if (*pcbStructInfo
< bytesNeeded
)
1887 *pcbStructInfo
= bytesNeeded
;
1888 SetLastError(ERROR_MORE_DATA
);
1893 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1900 pszObjId
+= sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1901 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1903 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1904 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1908 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1917 pszObjId
+= sprintf(pszObjId
, ".%d", val
);
1920 *pcbStructInfo
= bytesNeeded
;
1926 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1927 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1928 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1932 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
1933 pvStructInfo
, *pcbStructInfo
);
1936 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1937 else if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1938 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1939 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1941 SetLastError(CRYPT_E_ASN1_BADTAG
);
1945 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1946 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1947 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1950 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1952 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
1953 pvStructInfo
, *pcbStructInfo
);
1955 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1956 bytesNeeded
+= cbEncoded
;
1958 *pcbStructInfo
= bytesNeeded
;
1959 else if (*pcbStructInfo
< bytesNeeded
)
1961 SetLastError(ERROR_MORE_DATA
);
1962 *pcbStructInfo
= bytesNeeded
;
1967 PCRYPT_OBJID_BLOB blob
= pvStructInfo
;
1969 *pcbStructInfo
= bytesNeeded
;
1970 blob
->cbData
= cbEncoded
;
1971 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1972 blob
->pbData
= (LPBYTE
)pbEncoded
;
1975 assert(blob
->pbData
);
1976 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1982 static BOOL WINAPI
CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType
,
1983 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1984 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1986 CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
1987 struct AsnDecodeSequenceItem items
[] = {
1988 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1989 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1990 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1991 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1992 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1993 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1996 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
1997 pvStructInfo
, *pcbStructInfo
);
1999 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2000 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
,
2001 typeValue
? typeValue
->pszObjId
: NULL
);
2004 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
2005 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2006 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2008 CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
2010 struct AsnDecodeSequenceItem items
[] = {
2011 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2012 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2013 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2014 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2015 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2016 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2019 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2020 pvStructInfo
, *pcbStructInfo
);
2022 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2023 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2024 if (ret
&& pvStructInfo
)
2026 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2027 debugstr_a(algo
->pszObjId
));
2032 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
2033 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2034 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2036 struct SPCDigest
*digest
= pvStructInfo
;
2037 struct AsnDecodeSequenceItem items
[] = {
2038 { ASN_SEQUENCEOF
, offsetof(struct SPCDigest
, DigestAlgorithm
),
2039 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2041 offsetof(struct SPCDigest
, DigestAlgorithm
.pszObjId
), 0 },
2042 { ASN_OCTETSTRING
, offsetof(struct SPCDigest
, Digest
),
2043 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
),
2044 FALSE
, TRUE
, offsetof(struct SPCDigest
, Digest
.pbData
), 0 },
2047 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2048 pvStructInfo
, *pcbStructInfo
);
2050 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2051 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
,
2052 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
2055 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
2056 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2057 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2061 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2062 pvStructInfo
, *pcbStructInfo
);
2066 struct AsnDecodeSequenceItem items
[] = {
2067 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
2068 CRYPT_AsnDecodeAttributeTypeValue
,
2069 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
2070 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
2071 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
2072 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
2074 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
2077 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2078 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2082 SetLastError(STATUS_ACCESS_VIOLATION
);
2085 TRACE("returning %d\n", ret
);
2089 static BOOL WINAPI
CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType
,
2090 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2091 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2094 DWORD bytesNeeded
, dataLen
;
2096 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2098 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2100 bytesNeeded
= dataLen
+ 2 + sizeof(LPWSTR
);
2102 *pcbStructInfo
= bytesNeeded
;
2103 else if (*pcbStructInfo
< bytesNeeded
)
2105 *pcbStructInfo
= bytesNeeded
;
2106 SetLastError(ERROR_MORE_DATA
);
2114 *pcbStructInfo
= bytesNeeded
;
2115 assert(pvStructInfo
);
2116 str
= *(LPWSTR
*)pvStructInfo
;
2117 for (i
= 0; i
< dataLen
/ 2; i
++)
2118 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
2119 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
2120 /* Decoded string is always NULL-terminated */
2127 static BOOL WINAPI
CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType
,
2128 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2129 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2134 TRACE("(%p, %ld, %08lx, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
2135 pvStructInfo
, pvStructInfo
? *pcbStructInfo
: 0);
2137 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2139 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2141 ret
= CRYPT_AsnDecodeBMPString(dwCertEncodingType
, lpszStructType
,
2142 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pvStructInfo
,
2148 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
2149 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2150 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2154 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2155 pvStructInfo
, *pcbStructInfo
);
2159 struct AsnDecodeSequenceItem items
[] = {
2160 { ASN_CONSTRUCTOR
| ASN_CONTEXT
,
2161 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
),
2162 CRYPT_AsnDecodeProgramName
, sizeof(LPCWSTR
), TRUE
, TRUE
,
2163 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
), 0 },
2164 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
2165 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
),
2166 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2167 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
), 0 },
2168 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2,
2169 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
),
2170 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2171 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
), 0 },
2174 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2175 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2179 SetLastError(STATUS_ACCESS_VIOLATION
);
2182 TRACE("returning %d\n", ret
);
2186 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2187 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2188 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2189 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2194 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2196 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2198 if (dataLen
> sizeof(int))
2200 SetLastError(CRYPT_E_ASN1_LARGE
);
2203 else if (!pvStructInfo
)
2204 *pcbStructInfo
= sizeof(int);
2205 else if (*pcbStructInfo
< sizeof(int))
2207 *pcbStructInfo
= sizeof(int);
2208 SetLastError(ERROR_MORE_DATA
);
2216 *pcbStructInfo
= sizeof(int);
2217 if (dataLen
&& pbEncoded
[1 + lenBytes
] & 0x80)
2219 /* initialize to a negative value to sign-extend */
2224 for (i
= 0; i
< dataLen
; i
++)
2227 val
|= pbEncoded
[1 + lenBytes
+ i
];
2229 memcpy(pvStructInfo
, &val
, sizeof(int));
2235 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
2236 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2237 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2241 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2242 pvStructInfo
, *pcbStructInfo
);
2246 struct AsnDecodeSequenceItem items
[] = {
2247 { ASN_BMPSTRING
, offsetof(CAT_MEMBERINFO
, pwszSubjGuid
),
2248 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2249 offsetof(CAT_MEMBERINFO
, pwszSubjGuid
), 0 },
2250 { ASN_INTEGER
, offsetof(CAT_MEMBERINFO
, dwCertVersion
),
2251 CRYPT_AsnDecodeInt
, FINALMEMBERSIZE(CAT_MEMBERINFO
, dwCertVersion
),
2252 FALSE
, FALSE
, 0, 0 },
2255 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2256 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2260 SetLastError(STATUS_ACCESS_VIOLATION
);
2263 TRACE("returning %d\n", ret
);
2267 BOOL WINAPI
WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType
,
2268 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2269 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2273 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded
, cbEncoded
, dwFlags
,
2274 pvStructInfo
, *pcbStructInfo
);
2278 struct AsnDecodeSequenceItem items
[] = {
2279 { ASN_BMPSTRING
, offsetof(CAT_NAMEVALUE
, pwszTag
),
2280 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2281 offsetof(CAT_NAMEVALUE
, pwszTag
), 0 },
2282 { ASN_INTEGER
, offsetof(CAT_NAMEVALUE
, fdwFlags
),
2283 CRYPT_AsnDecodeInt
, MEMBERSIZE(CAT_NAMEVALUE
, fdwFlags
, Value
),
2284 FALSE
, FALSE
, 0, 0 },
2285 { ASN_OCTETSTRING
, offsetof(CAT_NAMEVALUE
, Value
),
2286 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2287 offsetof(CAT_NAMEVALUE
, Value
.pbData
), 0 },
2290 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2291 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2295 SetLastError(STATUS_ACCESS_VIOLATION
);
2298 TRACE("returning %d\n", ret
);
2302 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2303 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2304 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2310 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2313 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2315 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2318 if (pbEncoded
[1] > 1)
2320 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2325 *pcbStructInfo
= sizeof(BOOL
);
2328 else if (*pcbStructInfo
< sizeof(BOOL
))
2330 *pcbStructInfo
= sizeof(BOOL
);
2331 SetLastError(ERROR_MORE_DATA
);
2336 *pcbStructInfo
= sizeof(BOOL
);
2337 *(BOOL
*)pvStructInfo
= pbEncoded
[2] != 0;
2340 TRACE("returning %d (%08lx)\n", ret
, GetLastError());
2344 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType
,
2345 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2346 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2350 TRACE("(%p, %ld, %08lx, %p, %ld)\n", pbEncoded
, cbEncoded
, dwFlags
,
2351 pvStructInfo
, *pcbStructInfo
);
2355 struct AsnDecodeSequenceItem items
[] = {
2356 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fFinancialInfoAvailable
),
2357 CRYPT_AsnDecodeBool
, MEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2358 fFinancialInfoAvailable
, fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2359 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fMeetsCriteria
),
2360 CRYPT_AsnDecodeBool
, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2361 fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2364 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2365 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2369 SetLastError(STATUS_ACCESS_VIOLATION
);
2372 TRACE("returning %d\n", ret
);