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
24 #define NONAMELESSUNION
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("(%d, %p), %p, %d\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%08x, %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
->u
.pwszFile
?
151 lstrlenW(link
->u
.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
->u
.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
->u
.Moniker
.ClassId
),
189 (BYTE
*)link
->u
.Moniker
.ClassId
};
191 CRYPT_EncodeLen(classId
.cbData
, NULL
, &classIdLenBytes
);
192 CRYPT_EncodeLen(link
->u
.Moniker
.SerializedData
.cbData
, NULL
,
194 dataLen
= 2 + classIdLenBytes
+ classId
.cbData
+
195 dataLenBytes
+ link
->u
.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
->u
.Moniker
.SerializedData
.cbData
;
221 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
,
222 &link
->u
.Moniker
.SerializedData
, pbEncoded
, &size
);
228 case SPC_URL_LINK_CHOICE
:
233 /* Check for invalid characters in URL */
236 for (ptr
= link
->u
.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
->u
.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, %d, %p, %d\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%08x, %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 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
656 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
657 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
659 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
660 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
661 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
664 struct AsnEncodeSequenceItem items
[2] = {
665 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
666 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
669 if (algo
->Parameters
.cbData
)
670 items
[1].pvStructInfo
= &algo
->Parameters
;
672 items
[1].pvStructInfo
= &nullBlob
;
673 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
674 pbEncoded
, pcbEncoded
);
678 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
679 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
682 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
683 struct AsnEncodeSequenceItem items
[] = {
684 { &typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
685 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
688 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
689 pbEncoded
, pcbEncoded
);
694 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
695 CRYPT_HASH_BLOB Digest
;
698 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
699 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
702 const struct SPCDigest
*digest
= pvStructInfo
;
703 struct AsnEncodeSequenceItem items
[] = {
704 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
705 { &digest
->Digest
, CRYPT_CopyEncodedBlob
, 0 },
708 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
709 pbEncoded
, pcbEncoded
);
712 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
713 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
718 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
719 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
723 const SPC_INDIRECT_DATA_CONTENT
*data
= pvStructInfo
;
724 struct AsnEncodeSequenceItem items
[] = {
725 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
726 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
729 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
730 pbEncoded
, pcbEncoded
);
734 SetLastError(STATUS_ACCESS_VIOLATION
);
740 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
741 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
745 LPCWSTR str
= pvStructInfo
;
746 DWORD bytesNeeded
, lenBytes
, strLen
;
749 strLen
= lstrlenW(str
);
752 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
753 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
755 *pcbEncoded
= bytesNeeded
;
756 else if (*pcbEncoded
< bytesNeeded
)
758 *pcbEncoded
= bytesNeeded
;
759 SetLastError(ERROR_MORE_DATA
);
766 *pcbEncoded
= bytesNeeded
;
767 *pbEncoded
++ = ASN_BMPSTRING
;
768 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
769 pbEncoded
+= lenBytes
;
770 for (i
= 0; i
< strLen
; i
++)
772 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
773 *pbEncoded
++ = str
[i
] & 0x00ff;
779 struct AsnEncodeTagSwappedItem
782 const void *pvStructInfo
;
783 CryptEncodeObjectFunc encodeFunc
;
786 /* Sort of a wacky hack, it encodes something using the struct
787 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
788 * given in the struct AsnEncodeTagSwappedItem.
790 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
791 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
795 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
797 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
798 item
->pvStructInfo
, pbEncoded
, pcbEncoded
);
799 if (ret
&& pbEncoded
)
800 *pbEncoded
= item
->tag
;
804 BOOL WINAPI
WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType
,
805 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
810 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
811 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
815 const SPC_SP_OPUS_INFO
*info
= pvStructInfo
;
817 if (info
->pMoreInfo
&&
818 info
->pMoreInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
819 info
->pMoreInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
820 info
->pMoreInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
821 SetLastError(E_INVALIDARG
);
822 else if (info
->pPublisherInfo
&&
823 info
->pPublisherInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
824 info
->pPublisherInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
825 info
->pPublisherInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
826 SetLastError(E_INVALIDARG
);
829 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
830 struct AsnConstructedItem constructed
[3] = { { 0 } };
831 struct AsnEncodeTagSwappedItem swapped
;
832 DWORD cItem
= 0, cConstructed
= 0;
834 if (info
->pwszProgramName
)
836 swapped
.tag
= ASN_CONTEXT
;
837 swapped
.pvStructInfo
= info
->pwszProgramName
;
838 swapped
.encodeFunc
= CRYPT_AsnEncodeBMPString
;
839 constructed
[cConstructed
].tag
= 0;
840 constructed
[cConstructed
].pvStructInfo
= &swapped
;
841 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
842 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
843 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
849 constructed
[cConstructed
].tag
= 1;
850 constructed
[cConstructed
].pvStructInfo
= info
->pMoreInfo
;
851 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
852 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
853 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
857 if (info
->pPublisherInfo
)
859 constructed
[cConstructed
].tag
= 2;
860 constructed
[cConstructed
].pvStructInfo
= info
->pPublisherInfo
;
861 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
862 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
863 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
867 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
868 items
, cItem
, pbEncoded
, pcbEncoded
);
873 SetLastError(STATUS_ACCESS_VIOLATION
);
879 static BOOL
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
880 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
887 DWORD significantBytes
, lenBytes
, bytesNeeded
;
890 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
892 significantBytes
= blob
->cbData
;
893 if (significantBytes
)
895 if (blob
->pbData
[significantBytes
- 1] & 0x80)
897 /* negative, lop off leading (little-endian) 0xffs */
898 for (; significantBytes
> 0 &&
899 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
901 if (blob
->pbData
[significantBytes
- 1] < 0x80)
909 /* positive, lop off leading (little-endian) zeroes */
910 for (; significantBytes
> 0 &&
911 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
913 if (significantBytes
== 0)
914 significantBytes
= 1;
915 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
923 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
925 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
926 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
931 *pcbEncoded
= bytesNeeded
;
934 else if (*pcbEncoded
< bytesNeeded
)
936 *pcbEncoded
= bytesNeeded
;
937 SetLastError(ERROR_MORE_DATA
);
942 *pcbEncoded
= bytesNeeded
;
943 *pbEncoded
++ = ASN_INTEGER
;
946 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
947 pbEncoded
+= lenBytes
;
948 *pbEncoded
++ = padByte
;
952 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
953 pbEncoded
+= lenBytes
;
955 for (; significantBytes
> 0; significantBytes
--)
956 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
962 SetLastError(STATUS_ACCESS_VIOLATION
);
969 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
970 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
973 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
975 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
976 &blob
, pbEncoded
, pcbEncoded
);
979 BOOL WINAPI
WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType
,
980 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
985 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
986 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
990 const CAT_MEMBERINFO
*info
= pvStructInfo
;
991 struct AsnEncodeSequenceItem items
[] = {
992 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
993 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
996 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
997 pbEncoded
, pcbEncoded
);
1001 SetLastError(STATUS_ACCESS_VIOLATION
);
1007 BOOL WINAPI
WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType
,
1008 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1013 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1014 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1018 const CAT_NAMEVALUE
*value
= pvStructInfo
;
1019 struct AsnEncodeSequenceItem items
[] = {
1020 { value
->pwszTag
, CRYPT_AsnEncodeBMPString
, 0 },
1021 { &value
->fdwFlags
, CRYPT_AsnEncodeInt
, 0 },
1022 { &value
->Value
, CRYPT_AsnEncodeOctets
, 0 },
1025 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
1026 pbEncoded
, pcbEncoded
);
1030 SetLastError(STATUS_ACCESS_VIOLATION
);
1036 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1037 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1040 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1049 else if (*pcbEncoded
< 3)
1052 SetLastError(ERROR_MORE_DATA
);
1058 *pbEncoded
++ = ASN_BOOL
;
1060 *pbEncoded
++ = val
? 0xff : 0;
1063 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1067 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType
,
1068 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1073 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1074 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1078 const SPC_FINANCIAL_CRITERIA
*criteria
= pvStructInfo
;
1079 struct AsnEncodeSequenceItem items
[] = {
1080 { &criteria
->fFinancialInfoAvailable
, CRYPT_AsnEncodeBool
, 0 },
1081 { &criteria
->fMeetsCriteria
, CRYPT_AsnEncodeBool
, 0 },
1084 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
1085 pbEncoded
, pcbEncoded
);
1089 SetLastError(STATUS_ACCESS_VIOLATION
);
1095 /* Gets the number of length bytes from the given (leading) length byte */
1096 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1098 /* Helper function to get the encoded length of the data starting at pbEncoded,
1099 * where pbEncoded[0] is the tag. If the data are too short to contain a
1100 * length or if the length is too large for cbEncoded, sets an appropriate
1101 * error code and returns FALSE.
1103 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
1109 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1112 else if (pbEncoded
[1] <= 0x7f)
1114 if (pbEncoded
[1] + 1 > cbEncoded
)
1116 SetLastError(CRYPT_E_ASN1_EOD
);
1121 *len
= pbEncoded
[1];
1125 else if (pbEncoded
[1] == 0x80)
1127 FIXME("unimplemented for indefinite-length encoding\n");
1128 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1133 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
1135 if (lenLen
> sizeof(DWORD
) + 1)
1137 SetLastError(CRYPT_E_ASN1_LARGE
);
1140 else if (lenLen
+ 2 > cbEncoded
)
1142 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1153 out
|= *pbEncoded
++;
1155 if (out
+ lenLen
+ 1 > cbEncoded
)
1157 SetLastError(CRYPT_E_ASN1_EOD
);
1170 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
1171 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1172 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1175 DWORD bytesNeeded
, dataLen
;
1177 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1178 pvStructInfo
, *pcbStructInfo
);
1182 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1185 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
1187 SetLastError(CRYPT_E_ASN1_BADTAG
);
1190 else if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1192 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1193 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
1195 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
1197 *pcbStructInfo
= bytesNeeded
;
1198 else if (*pcbStructInfo
< bytesNeeded
)
1200 SetLastError(ERROR_MORE_DATA
);
1201 *pcbStructInfo
= bytesNeeded
;
1206 CRYPT_DATA_BLOB
*blob
;
1207 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1209 blob
= pvStructInfo
;
1210 blob
->cbData
= dataLen
;
1211 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1212 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
1215 assert(blob
->pbData
);
1217 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
1225 static BOOL
CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType
,
1226 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1227 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1230 DWORD bytesNeeded
= sizeof(SPC_LINK
), dataLen
;
1232 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1233 pvStructInfo
, *pcbStructInfo
);
1235 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1237 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1240 switch (pbEncoded
[0])
1243 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
1245 *pcbStructInfo
= bytesNeeded
;
1246 else if (*pcbStructInfo
< bytesNeeded
)
1248 *pcbStructInfo
= bytesNeeded
;
1249 SetLastError(ERROR_MORE_DATA
);
1254 PSPC_LINK link
= pvStructInfo
;
1257 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1258 for (i
= 0; i
< dataLen
; i
++)
1259 link
->u
.pwszUrl
[i
] =
1260 *(pbEncoded
+ 1 + lenBytes
+ i
);
1261 link
->u
.pwszUrl
[i
] = '\0';
1262 TRACE("returning url %s\n", debugstr_w(link
->u
.pwszUrl
));
1265 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1:
1267 CRYPT_DATA_BLOB classId
;
1268 DWORD size
= sizeof(classId
);
1270 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1271 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
1272 CRYPT_DECODE_NOCOPY_FLAG
, &classId
, &size
)))
1274 if (classId
.cbData
!= sizeof(SPC_UUID
))
1276 SetLastError(CRYPT_E_BAD_ENCODE
);
1281 CRYPT_DATA_BLOB data
;
1283 /* The tag length for the classId must be 1 since the
1284 * length is correct.
1286 size
= sizeof(data
);
1287 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1288 pbEncoded
+ 3 + lenBytes
+ classId
.cbData
,
1289 cbEncoded
- 3 - lenBytes
- classId
.cbData
,
1290 CRYPT_DECODE_NOCOPY_FLAG
, &data
, &size
)))
1292 bytesNeeded
+= data
.cbData
;
1294 *pcbStructInfo
= bytesNeeded
;
1295 else if (*pcbStructInfo
< bytesNeeded
)
1297 *pcbStructInfo
= bytesNeeded
;
1298 SetLastError(ERROR_MORE_DATA
);
1303 PSPC_LINK link
= pvStructInfo
;
1305 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1306 /* pwszFile pointer was set by caller, copy it
1307 * before overwriting it
1309 link
->u
.Moniker
.SerializedData
.pbData
=
1310 (BYTE
*)link
->u
.pwszFile
;
1311 memcpy(link
->u
.Moniker
.ClassId
, classId
.pbData
,
1313 memcpy(link
->u
.Moniker
.SerializedData
.pbData
,
1314 data
.pbData
, data
.cbData
);
1315 link
->u
.Moniker
.SerializedData
.cbData
= data
.cbData
;
1322 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2:
1323 if (dataLen
&& pbEncoded
[1 + lenBytes
] != ASN_CONTEXT
)
1324 SetLastError(CRYPT_E_ASN1_BADTAG
);
1325 else if ((ret
= CRYPT_GetLen(pbEncoded
+ 1 + lenBytes
, dataLen
,
1328 BYTE realLenBytes
= GET_LEN_BYTES(pbEncoded
[2 + lenBytes
]);
1330 bytesNeeded
+= realDataLen
+ sizeof(WCHAR
);
1332 *pcbStructInfo
= bytesNeeded
;
1333 else if (*pcbStructInfo
< bytesNeeded
)
1335 *pcbStructInfo
= bytesNeeded
;
1336 SetLastError(ERROR_MORE_DATA
);
1341 PSPC_LINK link
= pvStructInfo
;
1343 const BYTE
*ptr
= pbEncoded
+ 2 + lenBytes
+ realLenBytes
;
1345 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1346 for (i
= 0; i
< dataLen
/ sizeof(WCHAR
); i
++)
1347 link
->u
.pwszFile
[i
] =
1348 hton16(*(const WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1349 link
->u
.pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1350 TRACE("returning file %s\n", debugstr_w(link
->u
.pwszFile
));
1355 bytesNeeded
+= sizeof(WCHAR
);
1357 *pcbStructInfo
= bytesNeeded
;
1358 else if (*pcbStructInfo
< bytesNeeded
)
1360 *pcbStructInfo
= bytesNeeded
;
1361 SetLastError(ERROR_MORE_DATA
);
1366 PSPC_LINK link
= pvStructInfo
;
1368 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1369 link
->u
.pwszFile
[0] = '\0';
1375 SetLastError(CRYPT_E_ASN1_BADTAG
);
1378 TRACE("returning %d\n", ret
);
1382 BOOL WINAPI
WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType
,
1383 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1384 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1388 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1389 pvStructInfo
, *pcbStructInfo
);
1395 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1396 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, NULL
, &bytesNeeded
);
1400 *pcbStructInfo
= bytesNeeded
;
1401 else if (*pcbStructInfo
< bytesNeeded
)
1403 *pcbStructInfo
= bytesNeeded
;
1404 SetLastError(ERROR_MORE_DATA
);
1409 SPC_LINK
*link
= pvStructInfo
;
1412 (LPWSTR
)((BYTE
*)pvStructInfo
+ sizeof(SPC_LINK
));
1413 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1414 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1421 SetLastError(STATUS_ACCESS_VIOLATION
);
1424 TRACE("returning %d\n", ret
);
1428 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1429 DWORD
, DWORD
, void *, DWORD
*);
1432 * The expected tag of the item. If tag is 0, decodeFunc is called
1433 * regardless of the tag value seen.
1435 * A sequence is decoded into a struct. The offset member is the
1436 * offset of this item within that struct.
1438 * The decoder function to use. If this is NULL, then the member isn't
1439 * decoded, but minSize space is reserved for it.
1441 * The minimum amount of space occupied after decoding. You must set this.
1443 * If true, and the tag doesn't match the expected tag for this item,
1444 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1445 * filled with 0 for this member.
1446 * hasPointer, pointerOffset:
1447 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1448 * the offset within the struct of the data pointer (or to the
1449 * first data pointer, if more than one exist).
1451 * Used by CRYPT_AsnDecodeSequence, not for your use.
1453 struct AsnDecodeSequenceItem
1457 CryptDecodeObjectFunc decodeFunc
;
1461 DWORD pointerOffset
;
1465 /* Align up to a DWORD_PTR boundary
1467 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1))
1469 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
1470 #define MEMBERSIZE(s, member, nextmember) \
1471 (offsetof(s, nextmember) - offsetof(s, member))
1474 /* Decodes the items in a sequence, where the items are described in items,
1475 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1476 * pvStructInfo. nextData is a pointer to the memory location at which the
1477 * first decoded item with a dynamic pointer should point.
1478 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1480 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
1481 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1482 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
1486 DWORD i
, decoded
= 0;
1487 const BYTE
*ptr
= pbEncoded
;
1489 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
1490 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
1492 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
1494 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
1498 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
1501 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
1503 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
1505 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
1507 TRACE("Setting next pointer to %p\n",
1509 *(BYTE
**)((BYTE
*)pvStructInfo
+
1510 items
[i
].pointerOffset
) = nextData
;
1512 if (items
[i
].decodeFunc
)
1515 TRACE("decoding item %d\n", i
);
1517 TRACE("sizing item %d\n", i
);
1518 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
1519 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
1520 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
1521 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
1522 : NULL
, &items
[i
].size
);
1525 if (items
[i
].size
< items
[i
].minSize
)
1526 items
[i
].size
= items
[i
].minSize
;
1527 else if (items
[i
].size
> items
[i
].minSize
)
1529 /* Account for alignment padding */
1530 items
[i
].size
= ALIGN_DWORD_PTR(items
[i
].size
);
1532 TRACE("item %d size: %d\n", i
, items
[i
].size
);
1533 if (nextData
&& items
[i
].hasPointer
&&
1534 items
[i
].size
> items
[i
].minSize
)
1535 nextData
+= items
[i
].size
- items
[i
].minSize
;
1536 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1537 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1538 TRACE("item %d: decoded %d bytes\n", i
,
1539 1 + nextItemLenBytes
+ nextItemLen
);
1541 else if (items
[i
].optional
&&
1542 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1544 TRACE("skipping optional item %d\n", i
);
1545 items
[i
].size
= items
[i
].minSize
;
1546 SetLastError(NOERROR
);
1550 TRACE("item %d failed: %08x\n", i
,
1555 TRACE("item %d: decoded %d bytes\n", i
,
1556 1 + nextItemLenBytes
+ nextItemLen
);
1557 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1558 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1559 items
[i
].size
= items
[i
].minSize
;
1562 else if (items
[i
].optional
)
1564 TRACE("skipping optional item %d\n", i
);
1565 items
[i
].size
= items
[i
].minSize
;
1569 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1570 i
, ptr
[0], items
[i
].tag
);
1571 SetLastError(CRYPT_E_ASN1_BADTAG
);
1576 else if (items
[i
].optional
)
1578 TRACE("missing optional item %d, skipping\n", i
);
1579 items
[i
].size
= items
[i
].minSize
;
1583 TRACE("not enough bytes for item %d, failing\n", i
);
1584 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1589 *cbDecoded
= decoded
;
1590 TRACE("returning %d\n", ret
);
1594 /* This decodes an arbitrary sequence into a contiguous block of memory
1595 * (basically, a struct.) Each element being decoded is described by a struct
1596 * AsnDecodeSequenceItem, see above.
1597 * startingPointer is an optional pointer to the first place where dynamic
1598 * data will be stored. If you know the starting offset, you may pass it
1599 * here. Otherwise, pass NULL, and one will be inferred from the items.
1601 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1602 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1603 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1604 void *startingPointer
)
1608 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items
, cItem
, pbEncoded
,
1609 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1611 if (pbEncoded
[0] == ASN_SEQUENCE
)
1615 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1617 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1618 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1620 cbEncoded
-= 1 + lenBytes
;
1621 if (cbEncoded
< dataLen
)
1623 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
1625 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1629 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1630 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1631 if (ret
&& cbDecoded
!= dataLen
)
1633 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
1635 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1640 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1642 for (i
= 0; i
< cItem
; i
++)
1644 bytesNeeded
+= items
[i
].size
;
1645 structSize
+= items
[i
].minSize
;
1648 *pcbStructInfo
= bytesNeeded
;
1649 else if (*pcbStructInfo
< bytesNeeded
)
1651 SetLastError(ERROR_MORE_DATA
);
1652 *pcbStructInfo
= bytesNeeded
;
1659 *pcbStructInfo
= bytesNeeded
;
1660 if (startingPointer
)
1661 nextData
= startingPointer
;
1663 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1664 memset(pvStructInfo
, 0, structSize
);
1665 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1666 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1674 SetLastError(CRYPT_E_ASN1_BADTAG
);
1677 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1681 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1682 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1683 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1687 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
1688 pvStructInfo
, *pcbStructInfo
);
1690 if (pbEncoded
[0] == ASN_BITSTRING
)
1692 DWORD bytesNeeded
, dataLen
;
1694 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1696 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1697 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1699 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1701 *pcbStructInfo
= bytesNeeded
;
1702 else if (*pcbStructInfo
< bytesNeeded
)
1704 *pcbStructInfo
= bytesNeeded
;
1705 SetLastError(ERROR_MORE_DATA
);
1710 CRYPT_BIT_BLOB
*blob
;
1712 blob
= pvStructInfo
;
1713 blob
->cbData
= dataLen
- 1;
1714 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1715 GET_LEN_BYTES(pbEncoded
[1]));
1716 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1718 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1719 GET_LEN_BYTES(pbEncoded
[1]);
1723 assert(blob
->pbData
);
1726 BYTE mask
= 0xff << blob
->cUnusedBits
;
1728 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1729 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1730 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1738 SetLastError(CRYPT_E_ASN1_BADTAG
);
1741 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1745 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1746 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1747 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1752 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1754 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1756 SPC_LINK
**pLink
= pvStructInfo
;
1758 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1759 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1763 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1764 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1766 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1767 SetLastError(ERROR_MORE_DATA
);
1772 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1773 /* Set imageData's pointer if necessary */
1774 if (size
> sizeof(SPC_LINK
))
1776 (*pLink
)->u
.pwszUrl
=
1777 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1779 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1780 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1781 *pLink
, pcbStructInfo
);
1788 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1789 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1790 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1794 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1795 pvStructInfo
, *pcbStructInfo
);
1799 struct AsnDecodeSequenceItem items
[] = {
1800 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1801 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1802 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1803 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1804 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1805 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1808 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
1809 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
1813 SetLastError(STATUS_ACCESS_VIOLATION
);
1816 TRACE("returning %d\n", ret
);
1820 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1821 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1822 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1827 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1828 pvStructInfo
, *pcbStructInfo
);
1830 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1832 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1833 DWORD bytesNeeded
= sizeof(LPSTR
);
1837 /* The largest possible string for the first two components
1838 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1843 sprintf(firstTwo
, "%d.%d",
1844 pbEncoded
[1 + lenBytes
] / 40,
1845 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1847 bytesNeeded
+= strlen(firstTwo
) + 1;
1848 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1849 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1851 /* large enough for ".4000000" */
1855 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1862 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1865 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1872 snprintf(str
, sizeof(str
), ".%d", val
);
1873 bytesNeeded
+= strlen(str
);
1878 *pcbStructInfo
= bytesNeeded
;
1879 else if (*pcbStructInfo
< bytesNeeded
)
1881 *pcbStructInfo
= bytesNeeded
;
1882 SetLastError(ERROR_MORE_DATA
);
1890 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1893 pszObjId
+= sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1894 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1896 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1897 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1901 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1910 pszObjId
+= sprintf(pszObjId
, ".%d", val
);
1914 *(LPSTR
*)pvStructInfo
= NULL
;
1915 *pcbStructInfo
= bytesNeeded
;
1921 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1922 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1923 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1927 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1928 pvStructInfo
, *pcbStructInfo
);
1931 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1932 else if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1933 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1934 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1936 SetLastError(CRYPT_E_ASN1_BADTAG
);
1940 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1941 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1942 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1945 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1947 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1948 pvStructInfo
, *pcbStructInfo
);
1950 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1951 bytesNeeded
+= cbEncoded
;
1953 *pcbStructInfo
= bytesNeeded
;
1954 else if (*pcbStructInfo
< bytesNeeded
)
1956 SetLastError(ERROR_MORE_DATA
);
1957 *pcbStructInfo
= bytesNeeded
;
1962 PCRYPT_OBJID_BLOB blob
= pvStructInfo
;
1964 *pcbStructInfo
= bytesNeeded
;
1965 blob
->cbData
= cbEncoded
;
1966 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1967 blob
->pbData
= (LPBYTE
)pbEncoded
;
1970 assert(blob
->pbData
);
1971 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1977 static BOOL WINAPI
CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType
,
1978 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1979 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1981 CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
1982 struct AsnDecodeSequenceItem items
[] = {
1983 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1984 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1985 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1986 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1987 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1988 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1991 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1992 pvStructInfo
, *pcbStructInfo
);
1994 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
1995 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
,
1996 typeValue
? typeValue
->pszObjId
: NULL
);
1999 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
2000 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2001 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2003 CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
2005 struct AsnDecodeSequenceItem items
[] = {
2006 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2007 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2008 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2009 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2010 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2011 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2014 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2015 pvStructInfo
, *pcbStructInfo
);
2017 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2018 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2019 if (ret
&& pvStructInfo
)
2021 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2022 debugstr_a(algo
->pszObjId
));
2027 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
2028 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2029 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2031 struct SPCDigest
*digest
= 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
, ARRAY_SIZE(items
),
2046 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
,
2047 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
2050 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
2051 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2052 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2056 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2057 pvStructInfo
, *pcbStructInfo
);
2061 struct AsnDecodeSequenceItem items
[] = {
2062 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
2063 CRYPT_AsnDecodeAttributeTypeValue
,
2064 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
2065 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
2066 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
2067 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
2069 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
2072 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2073 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2077 SetLastError(STATUS_ACCESS_VIOLATION
);
2080 TRACE("returning %d\n", ret
);
2084 static BOOL WINAPI
CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType
,
2085 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2086 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2089 DWORD bytesNeeded
, dataLen
;
2091 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2093 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2095 bytesNeeded
= dataLen
+ 2 + sizeof(LPWSTR
);
2097 *pcbStructInfo
= bytesNeeded
;
2098 else if (*pcbStructInfo
< bytesNeeded
)
2100 *pcbStructInfo
= bytesNeeded
;
2101 SetLastError(ERROR_MORE_DATA
);
2109 *pcbStructInfo
= bytesNeeded
;
2110 assert(pvStructInfo
);
2111 str
= *(LPWSTR
*)pvStructInfo
;
2112 for (i
= 0; i
< dataLen
/ 2; i
++)
2113 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
2114 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
2115 /* Decoded string is always NULL-terminated */
2122 static BOOL WINAPI
CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType
,
2123 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2124 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2129 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2130 pvStructInfo
, pvStructInfo
? *pcbStructInfo
: 0);
2132 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2134 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2136 ret
= CRYPT_AsnDecodeBMPString(dwCertEncodingType
, lpszStructType
,
2137 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pvStructInfo
,
2143 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
2144 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2145 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2149 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2150 pvStructInfo
, *pcbStructInfo
);
2154 struct AsnDecodeSequenceItem items
[] = {
2155 { ASN_CONSTRUCTOR
| ASN_CONTEXT
,
2156 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
),
2157 CRYPT_AsnDecodeProgramName
, sizeof(LPCWSTR
), TRUE
, TRUE
,
2158 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
), 0 },
2159 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
2160 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
),
2161 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2162 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
), 0 },
2163 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2,
2164 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
),
2165 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2166 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
), 0 },
2169 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2170 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2174 SetLastError(STATUS_ACCESS_VIOLATION
);
2177 TRACE("returning %d\n", ret
);
2181 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2182 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2183 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2184 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2189 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2191 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2193 if (dataLen
> sizeof(int))
2195 SetLastError(CRYPT_E_ASN1_LARGE
);
2198 else if (!pvStructInfo
)
2199 *pcbStructInfo
= sizeof(int);
2200 else if (*pcbStructInfo
< sizeof(int))
2202 *pcbStructInfo
= sizeof(int);
2203 SetLastError(ERROR_MORE_DATA
);
2211 *pcbStructInfo
= sizeof(int);
2212 if (dataLen
&& pbEncoded
[1 + lenBytes
] & 0x80)
2214 /* initialize to a negative value to sign-extend */
2219 for (i
= 0; i
< dataLen
; i
++)
2222 val
|= pbEncoded
[1 + lenBytes
+ i
];
2224 memcpy(pvStructInfo
, &val
, sizeof(int));
2230 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
2231 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2232 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2236 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2237 pvStructInfo
, *pcbStructInfo
);
2241 struct AsnDecodeSequenceItem items
[] = {
2242 { ASN_BMPSTRING
, offsetof(CAT_MEMBERINFO
, pwszSubjGuid
),
2243 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2244 offsetof(CAT_MEMBERINFO
, pwszSubjGuid
), 0 },
2245 { ASN_INTEGER
, offsetof(CAT_MEMBERINFO
, dwCertVersion
),
2246 CRYPT_AsnDecodeInt
, FINALMEMBERSIZE(CAT_MEMBERINFO
, dwCertVersion
),
2247 FALSE
, FALSE
, 0, 0 },
2250 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2251 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2255 SetLastError(STATUS_ACCESS_VIOLATION
);
2258 TRACE("returning %d\n", ret
);
2262 BOOL WINAPI
WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType
,
2263 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2264 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2268 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2269 pvStructInfo
, *pcbStructInfo
);
2273 struct AsnDecodeSequenceItem items
[] = {
2274 { ASN_BMPSTRING
, offsetof(CAT_NAMEVALUE
, pwszTag
),
2275 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2276 offsetof(CAT_NAMEVALUE
, pwszTag
), 0 },
2277 { ASN_INTEGER
, offsetof(CAT_NAMEVALUE
, fdwFlags
),
2278 CRYPT_AsnDecodeInt
, MEMBERSIZE(CAT_NAMEVALUE
, fdwFlags
, Value
),
2279 FALSE
, FALSE
, 0, 0 },
2280 { ASN_OCTETSTRING
, offsetof(CAT_NAMEVALUE
, Value
),
2281 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2282 offsetof(CAT_NAMEVALUE
, Value
.pbData
), 0 },
2285 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2286 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2290 SetLastError(STATUS_ACCESS_VIOLATION
);
2293 TRACE("returning %d\n", ret
);
2297 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2298 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2299 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2305 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2308 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2310 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2313 if (pbEncoded
[1] > 1)
2315 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2320 *pcbStructInfo
= sizeof(BOOL
);
2323 else if (*pcbStructInfo
< sizeof(BOOL
))
2325 *pcbStructInfo
= sizeof(BOOL
);
2326 SetLastError(ERROR_MORE_DATA
);
2331 *pcbStructInfo
= sizeof(BOOL
);
2332 *(BOOL
*)pvStructInfo
= pbEncoded
[2] != 0;
2335 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2339 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType
,
2340 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2341 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2345 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2346 pvStructInfo
, *pcbStructInfo
);
2350 struct AsnDecodeSequenceItem items
[] = {
2351 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fFinancialInfoAvailable
),
2352 CRYPT_AsnDecodeBool
, MEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2353 fFinancialInfoAvailable
, fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2354 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fMeetsCriteria
),
2355 CRYPT_AsnDecodeBool
, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2356 fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2359 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2360 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2364 SetLastError(STATUS_ACCESS_VIOLATION
);
2367 TRACE("returning %d\n", ret
);