1 /* wintrust asn functions
3 * Copyright 2007 Juan Lang
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
36 #include "wine/exception.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
40 #ifdef WORDS_BIGENDIAN
47 #define hton16(x) RtlUshortByteSwap(x)
48 #define n16toh(x) RtlUshortByteSwap(x)
52 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
53 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
54 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
56 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
58 DWORD bytesNeeded
, significantBytes
= 0;
66 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
67 temp
<<= 8, significantBytes
--)
69 bytesNeeded
= significantBytes
+ 1;
73 *pcbEncoded
= bytesNeeded
;
76 if (*pcbEncoded
< bytesNeeded
)
78 SetLastError(ERROR_MORE_DATA
);
82 *pbEncoded
= (BYTE
)len
;
87 *pbEncoded
++ = significantBytes
| 0x80;
88 for (i
= 0; i
< significantBytes
; i
++)
90 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
94 *pcbEncoded
= bytesNeeded
;
98 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
99 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
103 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
104 DWORD bytesNeeded
, lenBytes
;
106 TRACE("(%d, %p), %p, %d\n", blob
->cbData
, blob
->pbData
, pbEncoded
,
109 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
110 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
112 *pcbEncoded
= bytesNeeded
;
113 else if (*pcbEncoded
< bytesNeeded
)
115 *pcbEncoded
= bytesNeeded
;
116 SetLastError(ERROR_MORE_DATA
);
121 *pbEncoded
++ = ASN_OCTETSTRING
;
122 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
123 pbEncoded
+= lenBytes
;
125 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
127 TRACE("returning %d\n", ret
);
131 BOOL WINAPI
WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType
,
132 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
137 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
138 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
143 const SPC_LINK
*link
= (const SPC_LINK
*)pvStructInfo
;
144 DWORD bytesNeeded
, lenBytes
;
146 switch (link
->dwLinkChoice
)
148 case SPC_FILE_LINK_CHOICE
:
150 DWORD fileNameLen
, fileNameLenBytes
;
153 fileNameLen
= link
->u
.pwszFile
?
154 lstrlenW(link
->u
.pwszFile
) * sizeof(WCHAR
) : 0;
155 CRYPT_EncodeLen(fileNameLen
, NULL
, &fileNameLenBytes
);
156 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, NULL
,
158 bytesNeeded
= 2 + lenBytes
+ fileNameLenBytes
+ fileNameLen
;
161 *pcbEncoded
= bytesNeeded
;
164 else if (*pcbEncoded
< bytesNeeded
)
166 SetLastError(ERROR_MORE_DATA
);
167 *pcbEncoded
= bytesNeeded
;
171 *pcbEncoded
= bytesNeeded
;
172 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2;
173 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, pbEncoded
,
175 pbEncoded
+= lenBytes
;
176 *pbEncoded
++ = ASN_CONTEXT
;
177 CRYPT_EncodeLen(fileNameLen
, pbEncoded
, &fileNameLenBytes
);
178 pbEncoded
+= fileNameLenBytes
;
179 for (ptr
= link
->u
.pwszFile
; ptr
&& *ptr
; ptr
++)
181 *(WCHAR
*)pbEncoded
= hton16(*ptr
);
182 pbEncoded
+= sizeof(WCHAR
);
188 case SPC_MONIKER_LINK_CHOICE
:
190 DWORD classIdLenBytes
, dataLenBytes
, dataLen
;
191 CRYPT_DATA_BLOB classId
= { sizeof(link
->u
.Moniker
.ClassId
),
192 (BYTE
*)link
->u
.Moniker
.ClassId
};
194 CRYPT_EncodeLen(classId
.cbData
, NULL
, &classIdLenBytes
);
195 CRYPT_EncodeLen(link
->u
.Moniker
.SerializedData
.cbData
, NULL
,
197 dataLen
= 2 + classIdLenBytes
+ classId
.cbData
+
198 dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
199 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
200 bytesNeeded
= 1 + dataLen
+ lenBytes
;
203 *pcbEncoded
= bytesNeeded
;
206 else if (*pcbEncoded
< bytesNeeded
)
208 SetLastError(ERROR_MORE_DATA
);
209 *pcbEncoded
= bytesNeeded
;
215 *pcbEncoded
= bytesNeeded
;
216 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
217 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
218 pbEncoded
+= lenBytes
;
219 size
= 1 + classIdLenBytes
+ classId
.cbData
;
220 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
, &classId
,
223 size
= 1 + dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
224 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
,
225 &link
->u
.Moniker
.SerializedData
, pbEncoded
, &size
);
231 case SPC_URL_LINK_CHOICE
:
236 /* Check for invalid characters in URL */
239 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
&& ret
; ptr
++)
243 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
250 CRYPT_EncodeLen(urlLen
, NULL
, &lenBytes
);
251 bytesNeeded
= 1 + lenBytes
+ urlLen
;
253 *pcbEncoded
= bytesNeeded
;
254 else if (*pcbEncoded
< bytesNeeded
)
256 SetLastError(ERROR_MORE_DATA
);
257 *pcbEncoded
= bytesNeeded
;
262 *pcbEncoded
= bytesNeeded
;
263 *pbEncoded
++ = ASN_CONTEXT
;
264 CRYPT_EncodeLen(urlLen
, pbEncoded
, &lenBytes
);
265 pbEncoded
+= lenBytes
;
266 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
; ptr
++)
267 *pbEncoded
++ = (BYTE
)*ptr
;
273 SetLastError(E_INVALIDARG
);
278 SetLastError(STATUS_ACCESS_VIOLATION
);
281 TRACE("returning %d\n", ret
);
285 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
288 struct AsnEncodeSequenceItem
290 const void *pvStructInfo
;
291 CryptEncodeObjectFunc encodeFunc
;
292 DWORD size
; /* used during encoding, not for your use */
295 static BOOL
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
296 struct AsnEncodeSequenceItem items
[], DWORD cItem
, BYTE
*pbEncoded
,
300 DWORD i
, dataLen
= 0;
302 TRACE("%p, %d, %p, %d\n", items
, cItem
, pbEncoded
, *pcbEncoded
);
303 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
305 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
306 items
[i
].pvStructInfo
, NULL
, &items
[i
].size
);
307 /* Some functions propagate their errors through the size */
309 *pcbEncoded
= items
[i
].size
;
310 dataLen
+= items
[i
].size
;
314 DWORD lenBytes
, bytesNeeded
;
316 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
317 bytesNeeded
= 1 + lenBytes
+ dataLen
;
319 *pcbEncoded
= bytesNeeded
;
320 else if (*pcbEncoded
< bytesNeeded
)
322 *pcbEncoded
= bytesNeeded
;
323 SetLastError(ERROR_MORE_DATA
);
328 *pcbEncoded
= bytesNeeded
;
329 *pbEncoded
++ = ASN_SEQUENCE
;
330 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
331 pbEncoded
+= lenBytes
;
332 for (i
= 0; ret
&& i
< cItem
; i
++)
334 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
335 items
[i
].pvStructInfo
, pbEncoded
, &items
[i
].size
);
336 /* Some functions propagate their errors through the size */
338 *pcbEncoded
= items
[i
].size
;
339 pbEncoded
+= items
[i
].size
;
343 TRACE("returning %d\n", ret
);
347 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
348 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
355 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
356 DWORD bytesNeeded
, lenBytes
, dataBytes
;
359 /* yep, MS allows cUnusedBits to be >= 8 */
360 if (!blob
->cUnusedBits
)
362 dataBytes
= blob
->cbData
;
365 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
367 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
368 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
376 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
377 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
380 *pcbEncoded
= bytesNeeded
;
383 else if (*pcbEncoded
< bytesNeeded
)
385 *pcbEncoded
= bytesNeeded
;
386 SetLastError(ERROR_MORE_DATA
);
391 *pcbEncoded
= bytesNeeded
;
392 *pbEncoded
++ = ASN_BITSTRING
;
393 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
394 pbEncoded
+= lenBytes
;
395 *pbEncoded
++ = unusedBits
;
398 BYTE mask
= 0xff << unusedBits
;
402 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
403 pbEncoded
+= dataBytes
- 1;
405 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
411 SetLastError(STATUS_ACCESS_VIOLATION
);
417 struct AsnConstructedItem
420 const void *pvStructInfo
;
421 CryptEncodeObjectFunc encodeFunc
;
424 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
425 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
429 const struct AsnConstructedItem
*item
=
430 (const struct AsnConstructedItem
*)pvStructInfo
;
433 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
434 item
->pvStructInfo
, NULL
, &len
)))
436 DWORD dataLen
, bytesNeeded
;
438 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
439 bytesNeeded
= 1 + dataLen
+ len
;
441 *pcbEncoded
= bytesNeeded
;
442 else if (*pcbEncoded
< bytesNeeded
)
444 *pcbEncoded
= bytesNeeded
;
445 SetLastError(ERROR_MORE_DATA
);
450 *pcbEncoded
= bytesNeeded
;
451 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
452 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
453 pbEncoded
+= dataLen
;
454 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
455 item
->pvStructInfo
, pbEncoded
, &len
);
458 /* Some functions propagate their errors through the size */
465 /* Some functions propagate their errors through the size */
472 BOOL WINAPI
WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType
,
473 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
476 const SPC_PE_IMAGE_DATA
*imageData
=
477 (const SPC_PE_IMAGE_DATA
*)pvStructInfo
;
480 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
481 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
486 struct AsnEncodeSequenceItem items
[2] = {
489 struct AsnConstructedItem constructed
= { 0, imageData
->pFile
,
490 WVTAsn1SpcLinkEncode
};
493 if (imageData
->Flags
.cbData
)
495 items
[cItem
].pvStructInfo
= &imageData
->Flags
;
496 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBits
;
499 if (imageData
->pFile
)
501 items
[cItem
].pvStructInfo
= &constructed
;
502 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
506 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
507 pbEncoded
, pcbEncoded
);
511 SetLastError(STATUS_ACCESS_VIOLATION
);
514 TRACE("returning %d\n", ret
);
518 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
519 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
522 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
523 DWORD bytesNeeded
= 0, lenBytes
;
528 TRACE("%s\n", debugstr_a(pszObjId
));
535 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
537 SetLastError(CRYPT_E_ASN1_ERROR
);
541 firstByte
= val1
* 40 + val2
;
542 ptr
= pszObjId
+ firstPos
;
552 /* note I assume each component is at most 32-bits long in base 2 */
553 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
555 if (val1
>= 0x10000000)
557 else if (val1
>= 0x200000)
559 else if (val1
>= 0x4000)
561 else if (val1
>= 0x80)
571 SetLastError(CRYPT_E_ASN1_ERROR
);
575 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
579 bytesNeeded
+= 1 + lenBytes
;
582 if (*pcbEncoded
< bytesNeeded
)
584 SetLastError(ERROR_MORE_DATA
);
589 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
590 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
591 pbEncoded
+= lenBytes
;
597 *pbEncoded
++ = firstByte
;
598 ptr
= pszObjId
+ firstPos
;
601 sscanf(ptr
, "%d%n", &val
, &pos
);
603 unsigned char outBytes
[5];
606 if (val
>= 0x10000000)
608 else if (val
>= 0x200000)
610 else if (val
>= 0x4000)
612 else if (val
>= 0x80)
616 for (i
= numBytes
; i
> 0; i
--)
618 outBytes
[i
- 1] = val
& 0x7f;
621 for (i
= 0; i
< numBytes
- 1; i
++)
622 *pbEncoded
++ = outBytes
[i
] | 0x80;
623 *pbEncoded
++ = outBytes
[i
];
632 *pcbEncoded
= bytesNeeded
;
636 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
637 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
640 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
644 *pcbEncoded
= blob
->cbData
;
645 else if (*pcbEncoded
< blob
->cbData
)
647 *pcbEncoded
= blob
->cbData
;
648 SetLastError(ERROR_MORE_DATA
);
654 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
655 *pcbEncoded
= blob
->cbData
;
660 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
661 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
662 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
664 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
665 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
666 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
667 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
670 struct AsnEncodeSequenceItem items
[2] = {
671 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
672 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
675 if (algo
->Parameters
.cbData
)
676 items
[1].pvStructInfo
= &algo
->Parameters
;
678 items
[1].pvStructInfo
= &nullBlob
;
679 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
680 sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
684 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
685 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
688 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
=
689 (const CRYPT_ATTRIBUTE_TYPE_VALUE
*)pvStructInfo
;
690 struct AsnEncodeSequenceItem items
[] = {
691 { &typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
692 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
695 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
696 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
701 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
702 CRYPT_HASH_BLOB Digest
;
705 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
706 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
709 const struct SPCDigest
*digest
= (const struct SPCDigest
*)pvStructInfo
;
710 struct AsnEncodeSequenceItem items
[] = {
711 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
712 { &digest
->Digest
, CRYPT_CopyEncodedBlob
, 0 },
715 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
716 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
719 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
720 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
725 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
726 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
730 const SPC_INDIRECT_DATA_CONTENT
*data
=
731 (const SPC_INDIRECT_DATA_CONTENT
*)pvStructInfo
;
732 struct AsnEncodeSequenceItem items
[] = {
733 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
734 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
737 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
738 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
742 SetLastError(STATUS_ACCESS_VIOLATION
);
748 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
749 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
753 LPCWSTR str
= (LPCWSTR
)pvStructInfo
;
754 DWORD bytesNeeded
, lenBytes
, strLen
;
757 strLen
= lstrlenW(str
);
760 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
761 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
763 *pcbEncoded
= bytesNeeded
;
764 else if (*pcbEncoded
< bytesNeeded
)
766 *pcbEncoded
= bytesNeeded
;
767 SetLastError(ERROR_MORE_DATA
);
774 *pcbEncoded
= bytesNeeded
;
775 *pbEncoded
++ = ASN_BMPSTRING
;
776 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
777 pbEncoded
+= lenBytes
;
778 for (i
= 0; i
< strLen
; i
++)
780 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
781 *pbEncoded
++ = str
[i
] & 0x00ff;
787 struct AsnEncodeTagSwappedItem
790 const void *pvStructInfo
;
791 CryptEncodeObjectFunc encodeFunc
;
794 /* Sort of a wacky hack, it encodes something using the struct
795 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
796 * given in the struct AsnEncodeTagSwappedItem.
798 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
799 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
803 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
805 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
806 item
->pvStructInfo
, pbEncoded
, pcbEncoded
);
807 if (ret
&& pbEncoded
)
808 *pbEncoded
= item
->tag
;
812 BOOL WINAPI
WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType
,
813 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
818 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
819 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
823 const SPC_SP_OPUS_INFO
*info
= pvStructInfo
;
825 if (info
->pMoreInfo
&&
826 info
->pMoreInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
827 info
->pMoreInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
828 info
->pMoreInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
829 SetLastError(E_INVALIDARG
);
830 else if (info
->pPublisherInfo
&&
831 info
->pPublisherInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
832 info
->pPublisherInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
833 info
->pPublisherInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
834 SetLastError(E_INVALIDARG
);
837 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
838 struct AsnConstructedItem constructed
[3] = { { 0 } };
839 struct AsnEncodeTagSwappedItem swapped
;
840 DWORD cItem
= 0, cConstructed
= 0;
842 if (info
->pwszProgramName
)
844 swapped
.tag
= ASN_CONTEXT
;
845 swapped
.pvStructInfo
= info
->pwszProgramName
;
846 swapped
.encodeFunc
= CRYPT_AsnEncodeBMPString
;
847 constructed
[cConstructed
].tag
= 0;
848 constructed
[cConstructed
].pvStructInfo
= &swapped
;
849 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
850 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
851 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
857 constructed
[cConstructed
].tag
= 1;
858 constructed
[cConstructed
].pvStructInfo
= info
->pMoreInfo
;
859 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
860 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
861 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
865 if (info
->pPublisherInfo
)
867 constructed
[cConstructed
].tag
= 2;
868 constructed
[cConstructed
].pvStructInfo
= info
->pPublisherInfo
;
869 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
870 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
871 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
875 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
876 items
, cItem
, pbEncoded
, pcbEncoded
);
881 SetLastError(STATUS_ACCESS_VIOLATION
);
887 static BOOL
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
888 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
895 DWORD significantBytes
, lenBytes
, bytesNeeded
;
898 const CRYPT_INTEGER_BLOB
*blob
=
899 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
901 significantBytes
= blob
->cbData
;
902 if (significantBytes
)
904 if (blob
->pbData
[significantBytes
- 1] & 0x80)
906 /* negative, lop off leading (little-endian) 0xffs */
907 for (; significantBytes
> 0 &&
908 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
910 if (blob
->pbData
[significantBytes
- 1] < 0x80)
918 /* positive, lop off leading (little-endian) zeroes */
919 for (; significantBytes
> 0 &&
920 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
922 if (significantBytes
== 0)
923 significantBytes
= 1;
924 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
932 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
934 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
935 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
940 *pcbEncoded
= bytesNeeded
;
943 else if (*pcbEncoded
< bytesNeeded
)
945 *pcbEncoded
= bytesNeeded
;
946 SetLastError(ERROR_MORE_DATA
);
951 *pcbEncoded
= bytesNeeded
;
952 *pbEncoded
++ = ASN_INTEGER
;
955 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
956 pbEncoded
+= lenBytes
;
957 *pbEncoded
++ = padByte
;
961 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
962 pbEncoded
+= lenBytes
;
964 for (; significantBytes
> 0; significantBytes
--)
965 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
971 SetLastError(STATUS_ACCESS_VIOLATION
);
978 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
979 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
982 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
984 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
985 &blob
, pbEncoded
, pcbEncoded
);
988 BOOL WINAPI
WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType
,
989 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
994 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
995 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
999 const CAT_MEMBERINFO
*info
= (const CAT_MEMBERINFO
*)pvStructInfo
;
1000 struct AsnEncodeSequenceItem items
[] = {
1001 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
1002 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
1005 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1006 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1010 SetLastError(STATUS_ACCESS_VIOLATION
);
1016 BOOL WINAPI
WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType
,
1017 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1022 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1023 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1027 const CAT_NAMEVALUE
*value
= (const CAT_NAMEVALUE
*)pvStructInfo
;
1028 struct AsnEncodeSequenceItem items
[] = {
1029 { value
->pwszTag
, CRYPT_AsnEncodeBMPString
, 0 },
1030 { &value
->fdwFlags
, CRYPT_AsnEncodeInt
, 0 },
1031 { &value
->Value
, CRYPT_AsnEncodeOctets
, 0 },
1034 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1035 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1039 SetLastError(STATUS_ACCESS_VIOLATION
);
1045 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1046 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1049 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1058 else if (*pcbEncoded
< 3)
1061 SetLastError(ERROR_MORE_DATA
);
1067 *pbEncoded
++ = ASN_BOOL
;
1069 *pbEncoded
++ = val
? 0xff : 0;
1072 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1076 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType
,
1077 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1082 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1083 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1087 const SPC_FINANCIAL_CRITERIA
*criteria
= pvStructInfo
;
1088 struct AsnEncodeSequenceItem items
[] = {
1089 { &criteria
->fFinancialInfoAvailable
, CRYPT_AsnEncodeBool
, 0 },
1090 { &criteria
->fMeetsCriteria
, CRYPT_AsnEncodeBool
, 0 },
1093 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1094 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1098 SetLastError(STATUS_ACCESS_VIOLATION
);
1104 /* Gets the number of length bytes from the given (leading) length byte */
1105 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1107 /* Helper function to get the encoded length of the data starting at pbEncoded,
1108 * where pbEncoded[0] is the tag. If the data are too short to contain a
1109 * length or if the length is too large for cbEncoded, sets an appropriate
1110 * error code and returns FALSE.
1112 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
1118 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1121 else if (pbEncoded
[1] <= 0x7f)
1123 if (pbEncoded
[1] + 1 > cbEncoded
)
1125 SetLastError(CRYPT_E_ASN1_EOD
);
1130 *len
= pbEncoded
[1];
1134 else if (pbEncoded
[1] == 0x80)
1136 FIXME("unimplemented for indefinite-length encoding\n");
1137 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1142 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
1144 if (lenLen
> sizeof(DWORD
) + 1)
1146 SetLastError(CRYPT_E_ASN1_LARGE
);
1149 else if (lenLen
+ 2 > cbEncoded
)
1151 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1162 out
|= *pbEncoded
++;
1164 if (out
+ lenLen
+ 1 > cbEncoded
)
1166 SetLastError(CRYPT_E_ASN1_EOD
);
1179 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
1180 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1181 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1184 DWORD bytesNeeded
, dataLen
;
1186 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1187 pvStructInfo
, *pcbStructInfo
);
1191 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1194 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
1196 SetLastError(CRYPT_E_ASN1_BADTAG
);
1199 else if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1201 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1202 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
1204 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
1206 *pcbStructInfo
= bytesNeeded
;
1207 else if (*pcbStructInfo
< bytesNeeded
)
1209 SetLastError(ERROR_MORE_DATA
);
1210 *pcbStructInfo
= bytesNeeded
;
1215 CRYPT_DATA_BLOB
*blob
;
1216 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1218 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
1219 blob
->cbData
= dataLen
;
1220 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1221 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
1224 assert(blob
->pbData
);
1226 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
1234 static BOOL
CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType
,
1235 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1236 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1239 DWORD bytesNeeded
= sizeof(SPC_LINK
), dataLen
;
1241 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1242 pvStructInfo
, *pcbStructInfo
);
1244 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1246 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1249 switch (pbEncoded
[0])
1252 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
1254 *pcbStructInfo
= bytesNeeded
;
1255 else if (*pcbStructInfo
< bytesNeeded
)
1257 *pcbStructInfo
= bytesNeeded
;
1258 SetLastError(ERROR_MORE_DATA
);
1263 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1266 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1267 for (i
= 0; i
< dataLen
; i
++)
1268 link
->u
.pwszUrl
[i
] =
1269 *(pbEncoded
+ 1 + lenBytes
+ i
);
1270 link
->u
.pwszUrl
[i
] = '\0';
1271 TRACE("returning url %s\n", debugstr_w(link
->u
.pwszUrl
));
1274 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1:
1276 CRYPT_DATA_BLOB classId
;
1277 DWORD size
= sizeof(classId
);
1279 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1280 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
1281 CRYPT_DECODE_NOCOPY_FLAG
, &classId
, &size
)))
1283 if (classId
.cbData
!= sizeof(SPC_UUID
))
1285 SetLastError(CRYPT_E_BAD_ENCODE
);
1290 CRYPT_DATA_BLOB data
;
1292 /* The tag length for the classId must be 1 since the
1293 * length is correct.
1295 size
= sizeof(data
);
1296 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1297 pbEncoded
+ 3 + lenBytes
+ classId
.cbData
,
1298 cbEncoded
- 3 - lenBytes
- classId
.cbData
,
1299 CRYPT_DECODE_NOCOPY_FLAG
, &data
, &size
)))
1301 bytesNeeded
+= data
.cbData
;
1303 *pcbStructInfo
= bytesNeeded
;
1304 else if (*pcbStructInfo
< bytesNeeded
)
1306 *pcbStructInfo
= bytesNeeded
;
1307 SetLastError(ERROR_MORE_DATA
);
1312 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1314 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1315 /* pwszFile pointer was set by caller, copy it
1316 * before overwriting it
1318 link
->u
.Moniker
.SerializedData
.pbData
=
1319 (BYTE
*)link
->u
.pwszFile
;
1320 memcpy(link
->u
.Moniker
.ClassId
, classId
.pbData
,
1322 memcpy(link
->u
.Moniker
.SerializedData
.pbData
,
1323 data
.pbData
, data
.cbData
);
1324 link
->u
.Moniker
.SerializedData
.cbData
= data
.cbData
;
1331 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2:
1332 if (dataLen
&& pbEncoded
[1 + lenBytes
] != ASN_CONTEXT
)
1333 SetLastError(CRYPT_E_ASN1_BADTAG
);
1334 else if ((ret
= CRYPT_GetLen(pbEncoded
+ 1 + lenBytes
, dataLen
,
1337 BYTE realLenBytes
= GET_LEN_BYTES(pbEncoded
[2 + lenBytes
]);
1339 bytesNeeded
+= realDataLen
+ sizeof(WCHAR
);
1341 *pcbStructInfo
= bytesNeeded
;
1342 else if (*pcbStructInfo
< bytesNeeded
)
1344 *pcbStructInfo
= bytesNeeded
;
1345 SetLastError(ERROR_MORE_DATA
);
1350 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1352 const BYTE
*ptr
= pbEncoded
+ 2 + lenBytes
+ realLenBytes
;
1354 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1355 for (i
= 0; i
< dataLen
/ sizeof(WCHAR
); i
++)
1356 link
->u
.pwszFile
[i
] =
1357 hton16(*(WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1358 link
->u
.pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1359 TRACE("returning file %s\n", debugstr_w(link
->u
.pwszFile
));
1364 bytesNeeded
+= sizeof(WCHAR
);
1366 *pcbStructInfo
= bytesNeeded
;
1367 else if (*pcbStructInfo
< bytesNeeded
)
1369 *pcbStructInfo
= bytesNeeded
;
1370 SetLastError(ERROR_MORE_DATA
);
1375 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1377 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1378 link
->u
.pwszFile
[0] = '\0';
1384 SetLastError(CRYPT_E_ASN1_BADTAG
);
1387 TRACE("returning %d\n", ret
);
1391 BOOL WINAPI
WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType
,
1392 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1393 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1397 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1398 pvStructInfo
, *pcbStructInfo
);
1404 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1405 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, NULL
, &bytesNeeded
);
1409 *pcbStructInfo
= bytesNeeded
;
1410 else if (*pcbStructInfo
< bytesNeeded
)
1412 *pcbStructInfo
= bytesNeeded
;
1413 SetLastError(ERROR_MORE_DATA
);
1418 SPC_LINK
*link
= (SPC_LINK
*)pvStructInfo
;
1421 (LPWSTR
)((BYTE
*)pvStructInfo
+ sizeof(SPC_LINK
));
1422 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1423 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1430 SetLastError(STATUS_ACCESS_VIOLATION
);
1433 TRACE("returning %d\n", ret
);
1437 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1438 DWORD
, DWORD
, void *, DWORD
*);
1441 * The expected tag of the item. If tag is 0, decodeFunc is called
1442 * regardless of the tag value seen.
1444 * A sequence is decoded into a struct. The offset member is the
1445 * offset of this item within that struct.
1447 * The decoder function to use. If this is NULL, then the member isn't
1448 * decoded, but minSize space is reserved for it.
1450 * The minimum amount of space occupied after decoding. You must set this.
1452 * If true, and the tag doesn't match the expected tag for this item,
1453 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1454 * filled with 0 for this member.
1455 * hasPointer, pointerOffset:
1456 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1457 * the offset within the struct of the data pointer (or to the
1458 * first data pointer, if more than one exist).
1460 * Used by CRYPT_AsnDecodeSequence, not for your use.
1462 struct AsnDecodeSequenceItem
1466 CryptDecodeObjectFunc decodeFunc
;
1470 DWORD pointerOffset
;
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 /* Account for alignment padding */
1526 if (items
[i
].size
% sizeof(DWORD
))
1527 items
[i
].size
+= sizeof(DWORD
) -
1528 items
[i
].size
% sizeof(DWORD
);
1529 TRACE("item %d size: %d\n", i
, items
[i
].size
);
1530 if (nextData
&& items
[i
].hasPointer
&&
1531 items
[i
].size
> items
[i
].minSize
)
1532 nextData
+= items
[i
].size
- items
[i
].minSize
;
1533 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1534 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1535 TRACE("item %d: decoded %d bytes\n", i
,
1536 1 + nextItemLenBytes
+ nextItemLen
);
1538 else if (items
[i
].optional
&&
1539 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1541 TRACE("skipping optional item %d\n", i
);
1542 items
[i
].size
= items
[i
].minSize
;
1543 SetLastError(NOERROR
);
1547 TRACE("item %d failed: %08x\n", i
,
1552 TRACE("item %d: decoded %d bytes\n", i
,
1553 1 + nextItemLenBytes
+ nextItemLen
);
1554 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1555 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1556 items
[i
].size
= items
[i
].minSize
;
1559 else if (items
[i
].optional
)
1561 TRACE("skipping optional item %d\n", i
);
1562 items
[i
].size
= items
[i
].minSize
;
1566 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1567 i
, ptr
[0], items
[i
].tag
);
1568 SetLastError(CRYPT_E_ASN1_BADTAG
);
1573 else if (items
[i
].optional
)
1575 TRACE("missing optional item %d, skipping\n", i
);
1576 items
[i
].size
= items
[i
].minSize
;
1580 TRACE("not enough bytes for item %d, failing\n", i
);
1581 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1586 *cbDecoded
= decoded
;
1587 TRACE("returning %d\n", ret
);
1591 /* This decodes an arbitrary sequence into a contiguous block of memory
1592 * (basically, a struct.) Each element being decoded is described by a struct
1593 * AsnDecodeSequenceItem, see above.
1594 * startingPointer is an optional pointer to the first place where dynamic
1595 * data will be stored. If you know the starting offset, you may pass it
1596 * here. Otherwise, pass NULL, and one will be inferred from the items.
1598 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1599 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1600 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1601 void *startingPointer
)
1605 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items
, cItem
, pbEncoded
,
1606 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1608 if (pbEncoded
[0] == ASN_SEQUENCE
)
1612 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1614 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1615 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1617 cbEncoded
-= 1 + lenBytes
;
1618 if (cbEncoded
< dataLen
)
1620 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
1622 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1626 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1627 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1628 if (ret
&& cbDecoded
!= dataLen
)
1630 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
1632 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1637 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1639 for (i
= 0; i
< cItem
; i
++)
1641 bytesNeeded
+= items
[i
].size
;
1642 structSize
+= items
[i
].minSize
;
1645 *pcbStructInfo
= bytesNeeded
;
1646 else if (*pcbStructInfo
< bytesNeeded
)
1648 SetLastError(ERROR_MORE_DATA
);
1649 *pcbStructInfo
= bytesNeeded
;
1656 *pcbStructInfo
= bytesNeeded
;
1657 if (startingPointer
)
1658 nextData
= (BYTE
*)startingPointer
;
1660 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1661 memset(pvStructInfo
, 0, structSize
);
1662 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1663 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1671 SetLastError(CRYPT_E_ASN1_BADTAG
);
1674 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1678 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1679 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1680 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1684 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
1685 pvStructInfo
, *pcbStructInfo
);
1687 if (pbEncoded
[0] == ASN_BITSTRING
)
1689 DWORD bytesNeeded
, dataLen
;
1691 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1693 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1694 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1696 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1698 *pcbStructInfo
= bytesNeeded
;
1699 else if (*pcbStructInfo
< bytesNeeded
)
1701 *pcbStructInfo
= bytesNeeded
;
1702 SetLastError(ERROR_MORE_DATA
);
1707 CRYPT_BIT_BLOB
*blob
;
1709 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
1710 blob
->cbData
= dataLen
- 1;
1711 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1712 GET_LEN_BYTES(pbEncoded
[1]));
1713 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1715 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1716 GET_LEN_BYTES(pbEncoded
[1]);
1720 assert(blob
->pbData
);
1723 BYTE mask
= 0xff << blob
->cUnusedBits
;
1725 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1726 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1727 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1735 SetLastError(CRYPT_E_ASN1_BADTAG
);
1738 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1742 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1743 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1744 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1749 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1751 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1753 SPC_LINK
**pLink
= (SPC_LINK
**)pvStructInfo
;
1755 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1756 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1760 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1761 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1763 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1764 SetLastError(ERROR_MORE_DATA
);
1769 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1770 /* Set imageData's pointer if necessary */
1771 if (size
> sizeof(SPC_LINK
))
1773 (*pLink
)->u
.pwszUrl
=
1774 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1776 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1777 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1778 *pLink
, pcbStructInfo
);
1785 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1786 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1787 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1791 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1792 pvStructInfo
, *pcbStructInfo
);
1796 struct AsnDecodeSequenceItem items
[] = {
1797 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1798 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1799 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1800 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1801 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1802 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1805 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1806 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1807 pvStructInfo
, pcbStructInfo
, NULL
);
1811 SetLastError(STATUS_ACCESS_VIOLATION
);
1814 TRACE("returning %d\n", ret
);
1818 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1819 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1820 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1825 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1826 pvStructInfo
, *pcbStructInfo
);
1828 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1830 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1831 DWORD bytesNeeded
= sizeof(LPSTR
);
1835 /* The largest possible string for the first two components
1836 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1841 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1842 pbEncoded
[1 + lenBytes
] / 40,
1843 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1845 bytesNeeded
+= strlen(firstTwo
) + 1;
1846 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1847 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1849 /* large enough for ".4000000" */
1853 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1860 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1863 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1870 snprintf(str
, sizeof(str
), ".%d", val
);
1871 bytesNeeded
+= strlen(str
);
1876 *pcbStructInfo
= bytesNeeded
;
1877 else if (*pcbStructInfo
< bytesNeeded
)
1879 *pcbStructInfo
= bytesNeeded
;
1880 SetLastError(ERROR_MORE_DATA
);
1888 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1891 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1892 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1894 pszObjId
+= strlen(pszObjId
);
1895 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1896 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1900 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1909 sprintf(pszObjId
, ".%d", val
);
1910 pszObjId
+= strlen(pszObjId
);
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
= (PCRYPT_OBJID_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
=
1982 (CRYPT_ATTRIBUTE_TYPE_VALUE
*)pvStructInfo
;
1983 struct AsnDecodeSequenceItem items
[] = {
1984 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1985 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1986 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1987 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1988 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1989 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1992 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1993 pvStructInfo
, *pcbStructInfo
);
1995 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1996 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1997 pvStructInfo
, pcbStructInfo
,
1998 typeValue
? typeValue
->pszObjId
: NULL
);
2001 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
2002 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2003 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2005 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
2006 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
2008 struct AsnDecodeSequenceItem items
[] = {
2009 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2010 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2011 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2012 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2013 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2014 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2017 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2018 pvStructInfo
, *pcbStructInfo
);
2020 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2021 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2022 pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2023 if (ret
&& pvStructInfo
)
2025 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2026 debugstr_a(algo
->pszObjId
));
2031 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
2032 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2033 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2035 struct SPCDigest
*digest
=
2036 (struct SPCDigest
*)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, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2048 pvStructInfo
, *pcbStructInfo
);
2050 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2051 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2052 pvStructInfo
, pcbStructInfo
,
2053 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
2056 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
2057 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2058 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2062 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2063 pvStructInfo
, *pcbStructInfo
);
2067 struct AsnDecodeSequenceItem items
[] = {
2068 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
2069 CRYPT_AsnDecodeAttributeTypeValue
,
2070 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
2071 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
2072 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
2073 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
2075 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
2078 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2079 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2080 pvStructInfo
, pcbStructInfo
, NULL
);
2084 SetLastError(STATUS_ACCESS_VIOLATION
);
2087 TRACE("returning %d\n", ret
);
2091 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
2092 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2093 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2095 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2096 pvStructInfo
, *pcbStructInfo
);
2100 static BOOL WINAPI
CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType
,
2101 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2102 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2105 DWORD bytesNeeded
, dataLen
;
2107 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2109 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2111 bytesNeeded
= dataLen
+ 2 + sizeof(LPWSTR
);
2113 *pcbStructInfo
= bytesNeeded
;
2114 else if (*pcbStructInfo
< bytesNeeded
)
2116 *pcbStructInfo
= bytesNeeded
;
2117 SetLastError(ERROR_MORE_DATA
);
2125 *pcbStructInfo
= bytesNeeded
;
2126 assert(pvStructInfo
);
2127 str
= *(LPWSTR
*)pvStructInfo
;
2128 for (i
= 0; i
< dataLen
/ 2; i
++)
2129 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
2130 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
2131 /* Decoded string is always NULL-terminated */
2138 static BOOL
CRYPT_AsnDecodeInteger(const BYTE
*pbEncoded
,
2139 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2142 DWORD bytesNeeded
, dataLen
;
2144 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2146 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2148 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2150 *pcbStructInfo
= bytesNeeded
;
2151 else if (*pcbStructInfo
< bytesNeeded
)
2153 *pcbStructInfo
= bytesNeeded
;
2154 SetLastError(ERROR_MORE_DATA
);
2159 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2161 *pcbStructInfo
= bytesNeeded
;
2162 blob
->cbData
= dataLen
;
2163 assert(blob
->pbData
);
2168 for (i
= 0; i
< blob
->cbData
; i
++)
2170 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
2179 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2180 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2181 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2182 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2185 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
2186 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
2187 DWORD size
= sizeof(buf
);
2189 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
2190 ret
= CRYPT_AsnDecodeInteger(pbEncoded
, cbEncoded
, 0, buf
, &size
);
2194 *pcbStructInfo
= sizeof(int);
2195 else if (*pcbStructInfo
< sizeof(int))
2197 *pcbStructInfo
= sizeof(int);
2198 SetLastError(ERROR_MORE_DATA
);
2206 *pcbStructInfo
= sizeof(int);
2207 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
2209 /* initialize to a negative value to sign-extend */
2214 for (i
= 0; i
< blob
->cbData
; i
++)
2217 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
2219 memcpy(pvStructInfo
, &val
, sizeof(int));
2222 else if (GetLastError() == ERROR_MORE_DATA
)
2223 SetLastError(CRYPT_E_ASN1_LARGE
);
2227 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
2228 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2229 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2233 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2234 pvStructInfo
, *pcbStructInfo
);
2238 struct AsnDecodeSequenceItem items
[] = {
2239 { ASN_BMPSTRING
, offsetof(CAT_MEMBERINFO
, pwszSubjGuid
),
2240 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2241 offsetof(CAT_MEMBERINFO
, pwszSubjGuid
), 0 },
2242 { ASN_INTEGER
, offsetof(CAT_MEMBERINFO
, dwCertVersion
),
2243 CRYPT_AsnDecodeInt
, sizeof(DWORD
),
2244 FALSE
, FALSE
, 0, 0 },
2247 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2248 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2249 pvStructInfo
, pcbStructInfo
, NULL
);
2253 SetLastError(STATUS_ACCESS_VIOLATION
);
2256 TRACE("returning %d\n", ret
);
2260 BOOL WINAPI
WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType
,
2261 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2262 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2266 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2267 pvStructInfo
, *pcbStructInfo
);
2271 struct AsnDecodeSequenceItem items
[] = {
2272 { ASN_BMPSTRING
, offsetof(CAT_NAMEVALUE
, pwszTag
),
2273 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2274 offsetof(CAT_NAMEVALUE
, pwszTag
), 0 },
2275 { ASN_INTEGER
, offsetof(CAT_NAMEVALUE
, fdwFlags
),
2276 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2277 { ASN_OCTETSTRING
, offsetof(CAT_NAMEVALUE
, Value
),
2278 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2279 offsetof(CAT_NAMEVALUE
, Value
.pbData
), 0 },
2282 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2283 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2284 pvStructInfo
, pcbStructInfo
, NULL
);
2288 SetLastError(STATUS_ACCESS_VIOLATION
);
2291 TRACE("returning %d\n", ret
);
2295 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2296 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2297 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2303 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2306 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2308 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2311 if (pbEncoded
[1] > 1)
2313 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2318 *pcbStructInfo
= sizeof(BOOL
);
2321 else if (*pcbStructInfo
< sizeof(BOOL
))
2323 *pcbStructInfo
= sizeof(BOOL
);
2324 SetLastError(ERROR_MORE_DATA
);
2329 *pcbStructInfo
= sizeof(BOOL
);
2330 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
2333 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2337 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType
,
2338 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2339 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2343 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2344 pvStructInfo
, *pcbStructInfo
);
2348 struct AsnDecodeSequenceItem items
[] = {
2349 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fFinancialInfoAvailable
),
2350 CRYPT_AsnDecodeBool
, sizeof(BOOL
), FALSE
, FALSE
, 0, 0 },
2351 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fMeetsCriteria
),
2352 CRYPT_AsnDecodeBool
, sizeof(BOOL
), FALSE
, FALSE
, 0, 0 },
2355 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2356 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2357 pvStructInfo
, pcbStructInfo
, NULL
);
2361 SetLastError(STATUS_ACCESS_VIOLATION
);
2364 TRACE("returning %d\n", ret
);