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
= 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
= 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
= 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
= pvStructInfo
;
432 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
433 item
->pvStructInfo
, NULL
, &len
)))
435 DWORD dataLen
, bytesNeeded
;
437 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
438 bytesNeeded
= 1 + dataLen
+ len
;
440 *pcbEncoded
= bytesNeeded
;
441 else if (*pcbEncoded
< bytesNeeded
)
443 *pcbEncoded
= bytesNeeded
;
444 SetLastError(ERROR_MORE_DATA
);
449 *pcbEncoded
= bytesNeeded
;
450 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
451 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
452 pbEncoded
+= dataLen
;
453 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
454 item
->pvStructInfo
, pbEncoded
, &len
);
457 /* Some functions propagate their errors through the size */
464 /* Some functions propagate their errors through the size */
471 BOOL WINAPI
WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType
,
472 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
475 const SPC_PE_IMAGE_DATA
*imageData
= pvStructInfo
;
478 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
479 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
484 struct AsnEncodeSequenceItem items
[2] = {
487 struct AsnConstructedItem constructed
= { 0, imageData
->pFile
,
488 WVTAsn1SpcLinkEncode
};
491 if (imageData
->Flags
.cbData
)
493 items
[cItem
].pvStructInfo
= &imageData
->Flags
;
494 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBits
;
497 if (imageData
->pFile
)
499 items
[cItem
].pvStructInfo
= &constructed
;
500 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
504 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
505 pbEncoded
, pcbEncoded
);
509 SetLastError(STATUS_ACCESS_VIOLATION
);
512 TRACE("returning %d\n", ret
);
516 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
517 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
520 LPCSTR pszObjId
= pvStructInfo
;
521 DWORD bytesNeeded
= 0, lenBytes
;
526 TRACE("%s\n", debugstr_a(pszObjId
));
533 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
535 SetLastError(CRYPT_E_ASN1_ERROR
);
539 firstByte
= val1
* 40 + val2
;
540 ptr
= pszObjId
+ firstPos
;
550 /* note I assume each component is at most 32-bits long in base 2 */
551 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
553 if (val1
>= 0x10000000)
555 else if (val1
>= 0x200000)
557 else if (val1
>= 0x4000)
559 else if (val1
>= 0x80)
569 SetLastError(CRYPT_E_ASN1_ERROR
);
573 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
577 bytesNeeded
+= 1 + lenBytes
;
580 if (*pcbEncoded
< bytesNeeded
)
582 SetLastError(ERROR_MORE_DATA
);
587 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
588 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
589 pbEncoded
+= lenBytes
;
595 *pbEncoded
++ = firstByte
;
596 ptr
= pszObjId
+ firstPos
;
599 sscanf(ptr
, "%d%n", &val
, &pos
);
601 unsigned char outBytes
[5];
604 if (val
>= 0x10000000)
606 else if (val
>= 0x200000)
608 else if (val
>= 0x4000)
610 else if (val
>= 0x80)
614 for (i
= numBytes
; i
> 0; i
--)
616 outBytes
[i
- 1] = val
& 0x7f;
619 for (i
= 0; i
< numBytes
- 1; i
++)
620 *pbEncoded
++ = outBytes
[i
] | 0x80;
621 *pbEncoded
++ = outBytes
[i
];
630 *pcbEncoded
= bytesNeeded
;
634 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
635 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
638 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
642 *pcbEncoded
= blob
->cbData
;
643 else if (*pcbEncoded
< blob
->cbData
)
645 *pcbEncoded
= blob
->cbData
;
646 SetLastError(ERROR_MORE_DATA
);
652 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
653 *pcbEncoded
= blob
->cbData
;
658 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
659 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
660 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
662 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
663 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
664 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
667 struct AsnEncodeSequenceItem items
[2] = {
668 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
669 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
672 if (algo
->Parameters
.cbData
)
673 items
[1].pvStructInfo
= &algo
->Parameters
;
675 items
[1].pvStructInfo
= &nullBlob
;
676 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
677 pbEncoded
, pcbEncoded
);
681 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
682 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
685 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
686 struct AsnEncodeSequenceItem items
[] = {
687 { &typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
688 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
691 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
692 pbEncoded
, pcbEncoded
);
697 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
698 CRYPT_HASH_BLOB Digest
;
701 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
702 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
705 const struct SPCDigest
*digest
= pvStructInfo
;
706 struct AsnEncodeSequenceItem items
[] = {
707 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
708 { &digest
->Digest
, CRYPT_CopyEncodedBlob
, 0 },
711 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
712 pbEncoded
, pcbEncoded
);
715 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
716 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
721 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
722 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
726 const SPC_INDIRECT_DATA_CONTENT
*data
= pvStructInfo
;
727 struct AsnEncodeSequenceItem items
[] = {
728 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
729 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
732 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
733 pbEncoded
, pcbEncoded
);
737 SetLastError(STATUS_ACCESS_VIOLATION
);
743 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
744 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
748 LPCWSTR str
= pvStructInfo
;
749 DWORD bytesNeeded
, lenBytes
, strLen
;
752 strLen
= lstrlenW(str
);
755 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
756 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
758 *pcbEncoded
= bytesNeeded
;
759 else if (*pcbEncoded
< bytesNeeded
)
761 *pcbEncoded
= bytesNeeded
;
762 SetLastError(ERROR_MORE_DATA
);
769 *pcbEncoded
= bytesNeeded
;
770 *pbEncoded
++ = ASN_BMPSTRING
;
771 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
772 pbEncoded
+= lenBytes
;
773 for (i
= 0; i
< strLen
; i
++)
775 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
776 *pbEncoded
++ = str
[i
] & 0x00ff;
782 struct AsnEncodeTagSwappedItem
785 const void *pvStructInfo
;
786 CryptEncodeObjectFunc encodeFunc
;
789 /* Sort of a wacky hack, it encodes something using the struct
790 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
791 * given in the struct AsnEncodeTagSwappedItem.
793 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
794 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
798 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
800 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
801 item
->pvStructInfo
, pbEncoded
, pcbEncoded
);
802 if (ret
&& pbEncoded
)
803 *pbEncoded
= item
->tag
;
807 BOOL WINAPI
WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType
,
808 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
813 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
814 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
818 const SPC_SP_OPUS_INFO
*info
= pvStructInfo
;
820 if (info
->pMoreInfo
&&
821 info
->pMoreInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
822 info
->pMoreInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
823 info
->pMoreInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
824 SetLastError(E_INVALIDARG
);
825 else if (info
->pPublisherInfo
&&
826 info
->pPublisherInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
827 info
->pPublisherInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
828 info
->pPublisherInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
829 SetLastError(E_INVALIDARG
);
832 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
833 struct AsnConstructedItem constructed
[3] = { { 0 } };
834 struct AsnEncodeTagSwappedItem swapped
;
835 DWORD cItem
= 0, cConstructed
= 0;
837 if (info
->pwszProgramName
)
839 swapped
.tag
= ASN_CONTEXT
;
840 swapped
.pvStructInfo
= info
->pwszProgramName
;
841 swapped
.encodeFunc
= CRYPT_AsnEncodeBMPString
;
842 constructed
[cConstructed
].tag
= 0;
843 constructed
[cConstructed
].pvStructInfo
= &swapped
;
844 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
845 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
846 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
852 constructed
[cConstructed
].tag
= 1;
853 constructed
[cConstructed
].pvStructInfo
= info
->pMoreInfo
;
854 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
855 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
856 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
860 if (info
->pPublisherInfo
)
862 constructed
[cConstructed
].tag
= 2;
863 constructed
[cConstructed
].pvStructInfo
= info
->pPublisherInfo
;
864 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
865 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
866 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
870 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
871 items
, cItem
, pbEncoded
, pcbEncoded
);
876 SetLastError(STATUS_ACCESS_VIOLATION
);
882 static BOOL
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
883 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
890 DWORD significantBytes
, lenBytes
, bytesNeeded
;
893 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
895 significantBytes
= blob
->cbData
;
896 if (significantBytes
)
898 if (blob
->pbData
[significantBytes
- 1] & 0x80)
900 /* negative, lop off leading (little-endian) 0xffs */
901 for (; significantBytes
> 0 &&
902 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
904 if (blob
->pbData
[significantBytes
- 1] < 0x80)
912 /* positive, lop off leading (little-endian) zeroes */
913 for (; significantBytes
> 0 &&
914 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
916 if (significantBytes
== 0)
917 significantBytes
= 1;
918 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
926 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
928 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
929 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
934 *pcbEncoded
= bytesNeeded
;
937 else if (*pcbEncoded
< bytesNeeded
)
939 *pcbEncoded
= bytesNeeded
;
940 SetLastError(ERROR_MORE_DATA
);
945 *pcbEncoded
= bytesNeeded
;
946 *pbEncoded
++ = ASN_INTEGER
;
949 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
950 pbEncoded
+= lenBytes
;
951 *pbEncoded
++ = padByte
;
955 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
956 pbEncoded
+= lenBytes
;
958 for (; significantBytes
> 0; significantBytes
--)
959 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
965 SetLastError(STATUS_ACCESS_VIOLATION
);
972 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
973 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
976 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
978 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
979 &blob
, pbEncoded
, pcbEncoded
);
982 BOOL WINAPI
WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType
,
983 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
988 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
989 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
993 const CAT_MEMBERINFO
*info
= pvStructInfo
;
994 struct AsnEncodeSequenceItem items
[] = {
995 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
996 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
999 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
1000 pbEncoded
, pcbEncoded
);
1004 SetLastError(STATUS_ACCESS_VIOLATION
);
1010 BOOL WINAPI
WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType
,
1011 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1016 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1017 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1021 const CAT_NAMEVALUE
*value
= pvStructInfo
;
1022 struct AsnEncodeSequenceItem items
[] = {
1023 { value
->pwszTag
, CRYPT_AsnEncodeBMPString
, 0 },
1024 { &value
->fdwFlags
, CRYPT_AsnEncodeInt
, 0 },
1025 { &value
->Value
, CRYPT_AsnEncodeOctets
, 0 },
1028 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
1029 pbEncoded
, pcbEncoded
);
1033 SetLastError(STATUS_ACCESS_VIOLATION
);
1039 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1040 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1043 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1052 else if (*pcbEncoded
< 3)
1055 SetLastError(ERROR_MORE_DATA
);
1061 *pbEncoded
++ = ASN_BOOL
;
1063 *pbEncoded
++ = val
? 0xff : 0;
1066 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1070 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType
,
1071 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1076 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1077 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1081 const SPC_FINANCIAL_CRITERIA
*criteria
= pvStructInfo
;
1082 struct AsnEncodeSequenceItem items
[] = {
1083 { &criteria
->fFinancialInfoAvailable
, CRYPT_AsnEncodeBool
, 0 },
1084 { &criteria
->fMeetsCriteria
, CRYPT_AsnEncodeBool
, 0 },
1087 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
, items
, ARRAY_SIZE(items
),
1088 pbEncoded
, pcbEncoded
);
1092 SetLastError(STATUS_ACCESS_VIOLATION
);
1098 /* Gets the number of length bytes from the given (leading) length byte */
1099 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1101 /* Helper function to get the encoded length of the data starting at pbEncoded,
1102 * where pbEncoded[0] is the tag. If the data are too short to contain a
1103 * length or if the length is too large for cbEncoded, sets an appropriate
1104 * error code and returns FALSE.
1106 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
1112 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1115 else if (pbEncoded
[1] <= 0x7f)
1117 if (pbEncoded
[1] + 1 > cbEncoded
)
1119 SetLastError(CRYPT_E_ASN1_EOD
);
1124 *len
= pbEncoded
[1];
1128 else if (pbEncoded
[1] == 0x80)
1130 FIXME("unimplemented for indefinite-length encoding\n");
1131 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1136 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
1138 if (lenLen
> sizeof(DWORD
) + 1)
1140 SetLastError(CRYPT_E_ASN1_LARGE
);
1143 else if (lenLen
+ 2 > cbEncoded
)
1145 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1156 out
|= *pbEncoded
++;
1158 if (out
+ lenLen
+ 1 > cbEncoded
)
1160 SetLastError(CRYPT_E_ASN1_EOD
);
1173 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
1174 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1175 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1178 DWORD bytesNeeded
, dataLen
;
1180 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1181 pvStructInfo
, *pcbStructInfo
);
1185 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1188 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
1190 SetLastError(CRYPT_E_ASN1_BADTAG
);
1193 else if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1195 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1196 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
1198 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
1200 *pcbStructInfo
= bytesNeeded
;
1201 else if (*pcbStructInfo
< bytesNeeded
)
1203 SetLastError(ERROR_MORE_DATA
);
1204 *pcbStructInfo
= bytesNeeded
;
1209 CRYPT_DATA_BLOB
*blob
;
1210 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1212 blob
= pvStructInfo
;
1213 blob
->cbData
= dataLen
;
1214 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1215 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
1218 assert(blob
->pbData
);
1220 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
1228 static BOOL
CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType
,
1229 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1230 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1233 DWORD bytesNeeded
= sizeof(SPC_LINK
), dataLen
;
1235 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1236 pvStructInfo
, *pcbStructInfo
);
1238 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1240 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1243 switch (pbEncoded
[0])
1246 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
1248 *pcbStructInfo
= bytesNeeded
;
1249 else if (*pcbStructInfo
< bytesNeeded
)
1251 *pcbStructInfo
= bytesNeeded
;
1252 SetLastError(ERROR_MORE_DATA
);
1257 PSPC_LINK link
= pvStructInfo
;
1260 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1261 for (i
= 0; i
< dataLen
; i
++)
1262 link
->u
.pwszUrl
[i
] =
1263 *(pbEncoded
+ 1 + lenBytes
+ i
);
1264 link
->u
.pwszUrl
[i
] = '\0';
1265 TRACE("returning url %s\n", debugstr_w(link
->u
.pwszUrl
));
1268 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1:
1270 CRYPT_DATA_BLOB classId
;
1271 DWORD size
= sizeof(classId
);
1273 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1274 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
1275 CRYPT_DECODE_NOCOPY_FLAG
, &classId
, &size
)))
1277 if (classId
.cbData
!= sizeof(SPC_UUID
))
1279 SetLastError(CRYPT_E_BAD_ENCODE
);
1284 CRYPT_DATA_BLOB data
;
1286 /* The tag length for the classId must be 1 since the
1287 * length is correct.
1289 size
= sizeof(data
);
1290 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1291 pbEncoded
+ 3 + lenBytes
+ classId
.cbData
,
1292 cbEncoded
- 3 - lenBytes
- classId
.cbData
,
1293 CRYPT_DECODE_NOCOPY_FLAG
, &data
, &size
)))
1295 bytesNeeded
+= data
.cbData
;
1297 *pcbStructInfo
= bytesNeeded
;
1298 else if (*pcbStructInfo
< bytesNeeded
)
1300 *pcbStructInfo
= bytesNeeded
;
1301 SetLastError(ERROR_MORE_DATA
);
1306 PSPC_LINK link
= pvStructInfo
;
1308 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1309 /* pwszFile pointer was set by caller, copy it
1310 * before overwriting it
1312 link
->u
.Moniker
.SerializedData
.pbData
=
1313 (BYTE
*)link
->u
.pwszFile
;
1314 memcpy(link
->u
.Moniker
.ClassId
, classId
.pbData
,
1316 memcpy(link
->u
.Moniker
.SerializedData
.pbData
,
1317 data
.pbData
, data
.cbData
);
1318 link
->u
.Moniker
.SerializedData
.cbData
= data
.cbData
;
1325 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2:
1326 if (dataLen
&& pbEncoded
[1 + lenBytes
] != ASN_CONTEXT
)
1327 SetLastError(CRYPT_E_ASN1_BADTAG
);
1328 else if ((ret
= CRYPT_GetLen(pbEncoded
+ 1 + lenBytes
, dataLen
,
1331 BYTE realLenBytes
= GET_LEN_BYTES(pbEncoded
[2 + lenBytes
]);
1333 bytesNeeded
+= realDataLen
+ sizeof(WCHAR
);
1335 *pcbStructInfo
= bytesNeeded
;
1336 else if (*pcbStructInfo
< bytesNeeded
)
1338 *pcbStructInfo
= bytesNeeded
;
1339 SetLastError(ERROR_MORE_DATA
);
1344 PSPC_LINK link
= pvStructInfo
;
1346 const BYTE
*ptr
= pbEncoded
+ 2 + lenBytes
+ realLenBytes
;
1348 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1349 for (i
= 0; i
< dataLen
/ sizeof(WCHAR
); i
++)
1350 link
->u
.pwszFile
[i
] =
1351 hton16(*(const WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1352 link
->u
.pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1353 TRACE("returning file %s\n", debugstr_w(link
->u
.pwszFile
));
1358 bytesNeeded
+= sizeof(WCHAR
);
1360 *pcbStructInfo
= bytesNeeded
;
1361 else if (*pcbStructInfo
< bytesNeeded
)
1363 *pcbStructInfo
= bytesNeeded
;
1364 SetLastError(ERROR_MORE_DATA
);
1369 PSPC_LINK link
= pvStructInfo
;
1371 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1372 link
->u
.pwszFile
[0] = '\0';
1378 SetLastError(CRYPT_E_ASN1_BADTAG
);
1381 TRACE("returning %d\n", ret
);
1385 BOOL WINAPI
WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType
,
1386 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1387 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1391 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1392 pvStructInfo
, *pcbStructInfo
);
1398 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1399 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, NULL
, &bytesNeeded
);
1403 *pcbStructInfo
= bytesNeeded
;
1404 else if (*pcbStructInfo
< bytesNeeded
)
1406 *pcbStructInfo
= bytesNeeded
;
1407 SetLastError(ERROR_MORE_DATA
);
1412 SPC_LINK
*link
= pvStructInfo
;
1415 (LPWSTR
)((BYTE
*)pvStructInfo
+ sizeof(SPC_LINK
));
1416 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1417 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1424 SetLastError(STATUS_ACCESS_VIOLATION
);
1427 TRACE("returning %d\n", ret
);
1431 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1432 DWORD
, DWORD
, void *, DWORD
*);
1435 * The expected tag of the item. If tag is 0, decodeFunc is called
1436 * regardless of the tag value seen.
1438 * A sequence is decoded into a struct. The offset member is the
1439 * offset of this item within that struct.
1441 * The decoder function to use. If this is NULL, then the member isn't
1442 * decoded, but minSize space is reserved for it.
1444 * The minimum amount of space occupied after decoding. You must set this.
1446 * If true, and the tag doesn't match the expected tag for this item,
1447 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1448 * filled with 0 for this member.
1449 * hasPointer, pointerOffset:
1450 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1451 * the offset within the struct of the data pointer (or to the
1452 * first data pointer, if more than one exist).
1454 * Used by CRYPT_AsnDecodeSequence, not for your use.
1456 struct AsnDecodeSequenceItem
1460 CryptDecodeObjectFunc decodeFunc
;
1464 DWORD pointerOffset
;
1468 /* Align up to a DWORD_PTR boundary
1470 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1))
1472 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
1473 #define MEMBERSIZE(s, member, nextmember) \
1474 (offsetof(s, nextmember) - offsetof(s, member))
1477 /* Decodes the items in a sequence, where the items are described in items,
1478 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1479 * pvStructInfo. nextData is a pointer to the memory location at which the
1480 * first decoded item with a dynamic pointer should point.
1481 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1483 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
1484 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1485 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
1489 DWORD i
, decoded
= 0;
1490 const BYTE
*ptr
= pbEncoded
;
1492 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
1493 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
1495 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
1497 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
1501 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
1504 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
1506 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
1508 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
1510 TRACE("Setting next pointer to %p\n",
1512 *(BYTE
**)((BYTE
*)pvStructInfo
+
1513 items
[i
].pointerOffset
) = nextData
;
1515 if (items
[i
].decodeFunc
)
1518 TRACE("decoding item %d\n", i
);
1520 TRACE("sizing item %d\n", i
);
1521 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
1522 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
1523 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
1524 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
1525 : NULL
, &items
[i
].size
);
1528 if (items
[i
].size
< items
[i
].minSize
)
1529 items
[i
].size
= items
[i
].minSize
;
1530 else if (items
[i
].size
> items
[i
].minSize
)
1532 /* Account for alignment padding */
1533 items
[i
].size
= ALIGN_DWORD_PTR(items
[i
].size
);
1535 TRACE("item %d size: %d\n", i
, items
[i
].size
);
1536 if (nextData
&& items
[i
].hasPointer
&&
1537 items
[i
].size
> items
[i
].minSize
)
1538 nextData
+= items
[i
].size
- items
[i
].minSize
;
1539 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1540 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1541 TRACE("item %d: decoded %d bytes\n", i
,
1542 1 + nextItemLenBytes
+ nextItemLen
);
1544 else if (items
[i
].optional
&&
1545 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1547 TRACE("skipping optional item %d\n", i
);
1548 items
[i
].size
= items
[i
].minSize
;
1549 SetLastError(NOERROR
);
1553 TRACE("item %d failed: %08x\n", i
,
1558 TRACE("item %d: decoded %d bytes\n", i
,
1559 1 + nextItemLenBytes
+ nextItemLen
);
1560 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1561 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1562 items
[i
].size
= items
[i
].minSize
;
1565 else if (items
[i
].optional
)
1567 TRACE("skipping optional item %d\n", i
);
1568 items
[i
].size
= items
[i
].minSize
;
1572 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1573 i
, ptr
[0], items
[i
].tag
);
1574 SetLastError(CRYPT_E_ASN1_BADTAG
);
1579 else if (items
[i
].optional
)
1581 TRACE("missing optional item %d, skipping\n", i
);
1582 items
[i
].size
= items
[i
].minSize
;
1586 TRACE("not enough bytes for item %d, failing\n", i
);
1587 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1592 *cbDecoded
= decoded
;
1593 TRACE("returning %d\n", ret
);
1597 /* This decodes an arbitrary sequence into a contiguous block of memory
1598 * (basically, a struct.) Each element being decoded is described by a struct
1599 * AsnDecodeSequenceItem, see above.
1600 * startingPointer is an optional pointer to the first place where dynamic
1601 * data will be stored. If you know the starting offset, you may pass it
1602 * here. Otherwise, pass NULL, and one will be inferred from the items.
1604 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1605 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1606 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1607 void *startingPointer
)
1611 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items
, cItem
, pbEncoded
,
1612 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1614 if (pbEncoded
[0] == ASN_SEQUENCE
)
1618 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1620 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1621 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1623 cbEncoded
-= 1 + lenBytes
;
1624 if (cbEncoded
< dataLen
)
1626 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
1628 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1632 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1633 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1634 if (ret
&& cbDecoded
!= dataLen
)
1636 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
1638 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1643 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1645 for (i
= 0; i
< cItem
; i
++)
1647 bytesNeeded
+= items
[i
].size
;
1648 structSize
+= items
[i
].minSize
;
1651 *pcbStructInfo
= bytesNeeded
;
1652 else if (*pcbStructInfo
< bytesNeeded
)
1654 SetLastError(ERROR_MORE_DATA
);
1655 *pcbStructInfo
= bytesNeeded
;
1662 *pcbStructInfo
= bytesNeeded
;
1663 if (startingPointer
)
1664 nextData
= startingPointer
;
1666 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1667 memset(pvStructInfo
, 0, structSize
);
1668 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1669 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1677 SetLastError(CRYPT_E_ASN1_BADTAG
);
1680 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1684 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1685 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1686 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1690 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
1691 pvStructInfo
, *pcbStructInfo
);
1693 if (pbEncoded
[0] == ASN_BITSTRING
)
1695 DWORD bytesNeeded
, dataLen
;
1697 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1699 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1700 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1702 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1704 *pcbStructInfo
= bytesNeeded
;
1705 else if (*pcbStructInfo
< bytesNeeded
)
1707 *pcbStructInfo
= bytesNeeded
;
1708 SetLastError(ERROR_MORE_DATA
);
1713 CRYPT_BIT_BLOB
*blob
;
1715 blob
= pvStructInfo
;
1716 blob
->cbData
= dataLen
- 1;
1717 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1718 GET_LEN_BYTES(pbEncoded
[1]));
1719 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1721 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1722 GET_LEN_BYTES(pbEncoded
[1]);
1726 assert(blob
->pbData
);
1729 BYTE mask
= 0xff << blob
->cUnusedBits
;
1731 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1732 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1733 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1741 SetLastError(CRYPT_E_ASN1_BADTAG
);
1744 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1748 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1749 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1750 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1755 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1757 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1759 SPC_LINK
**pLink
= pvStructInfo
;
1761 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1762 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1766 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1767 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1769 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1770 SetLastError(ERROR_MORE_DATA
);
1775 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1776 /* Set imageData's pointer if necessary */
1777 if (size
> sizeof(SPC_LINK
))
1779 (*pLink
)->u
.pwszUrl
=
1780 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1782 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1783 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1784 *pLink
, pcbStructInfo
);
1791 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1792 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1793 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1797 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1798 pvStructInfo
, *pcbStructInfo
);
1802 struct AsnDecodeSequenceItem items
[] = {
1803 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1804 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1805 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1806 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1807 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1808 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1811 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
1812 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
1816 SetLastError(STATUS_ACCESS_VIOLATION
);
1819 TRACE("returning %d\n", ret
);
1823 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1824 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1825 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1830 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1831 pvStructInfo
, *pcbStructInfo
);
1833 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1835 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1836 DWORD bytesNeeded
= sizeof(LPSTR
);
1840 /* The largest possible string for the first two components
1841 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1846 sprintf(firstTwo
, "%d.%d",
1847 pbEncoded
[1 + lenBytes
] / 40,
1848 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1850 bytesNeeded
+= strlen(firstTwo
) + 1;
1851 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1852 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1854 /* large enough for ".4000000" */
1858 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1865 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1868 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1875 snprintf(str
, sizeof(str
), ".%d", val
);
1876 bytesNeeded
+= strlen(str
);
1881 *pcbStructInfo
= bytesNeeded
;
1882 else if (*pcbStructInfo
< bytesNeeded
)
1884 *pcbStructInfo
= bytesNeeded
;
1885 SetLastError(ERROR_MORE_DATA
);
1893 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1896 pszObjId
+= sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1897 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1899 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1900 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1904 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1913 pszObjId
+= sprintf(pszObjId
, ".%d", val
);
1917 *(LPSTR
*)pvStructInfo
= NULL
;
1918 *pcbStructInfo
= bytesNeeded
;
1924 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1925 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1926 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1930 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1931 pvStructInfo
, *pcbStructInfo
);
1934 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1935 else if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1936 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1937 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1939 SetLastError(CRYPT_E_ASN1_BADTAG
);
1943 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1944 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1945 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1948 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1950 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1951 pvStructInfo
, *pcbStructInfo
);
1953 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1954 bytesNeeded
+= cbEncoded
;
1956 *pcbStructInfo
= bytesNeeded
;
1957 else if (*pcbStructInfo
< bytesNeeded
)
1959 SetLastError(ERROR_MORE_DATA
);
1960 *pcbStructInfo
= bytesNeeded
;
1965 PCRYPT_OBJID_BLOB blob
= pvStructInfo
;
1967 *pcbStructInfo
= bytesNeeded
;
1968 blob
->cbData
= cbEncoded
;
1969 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1970 blob
->pbData
= (LPBYTE
)pbEncoded
;
1973 assert(blob
->pbData
);
1974 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1980 static BOOL WINAPI
CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType
,
1981 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1982 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1984 CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
1985 struct AsnDecodeSequenceItem items
[] = {
1986 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1987 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1988 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1989 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1990 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1991 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1994 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1995 pvStructInfo
, *pcbStructInfo
);
1997 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
1998 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
,
1999 typeValue
? typeValue
->pszObjId
: NULL
);
2002 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
2003 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2004 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2006 CRYPT_ALGORITHM_IDENTIFIER
*algo
= 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
, ARRAY_SIZE(items
),
2021 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2022 if (ret
&& pvStructInfo
)
2024 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2025 debugstr_a(algo
->pszObjId
));
2030 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
2031 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2032 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2034 struct SPCDigest
*digest
= pvStructInfo
;
2035 struct AsnDecodeSequenceItem items
[] = {
2036 { ASN_SEQUENCEOF
, offsetof(struct SPCDigest
, DigestAlgorithm
),
2037 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2039 offsetof(struct SPCDigest
, DigestAlgorithm
.pszObjId
), 0 },
2040 { ASN_OCTETSTRING
, offsetof(struct SPCDigest
, Digest
),
2041 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
),
2042 FALSE
, TRUE
, offsetof(struct SPCDigest
, Digest
.pbData
), 0 },
2045 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2046 pvStructInfo
, *pcbStructInfo
);
2048 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2049 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
,
2050 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
2053 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
2054 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2055 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2059 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2060 pvStructInfo
, *pcbStructInfo
);
2064 struct AsnDecodeSequenceItem items
[] = {
2065 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
2066 CRYPT_AsnDecodeAttributeTypeValue
,
2067 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
2068 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
2069 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
2070 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
2072 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
2075 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2076 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2080 SetLastError(STATUS_ACCESS_VIOLATION
);
2083 TRACE("returning %d\n", ret
);
2087 static BOOL WINAPI
CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType
,
2088 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2089 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2092 DWORD bytesNeeded
, dataLen
;
2094 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2096 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2098 bytesNeeded
= dataLen
+ 2 + sizeof(LPWSTR
);
2100 *pcbStructInfo
= bytesNeeded
;
2101 else if (*pcbStructInfo
< bytesNeeded
)
2103 *pcbStructInfo
= bytesNeeded
;
2104 SetLastError(ERROR_MORE_DATA
);
2112 *pcbStructInfo
= bytesNeeded
;
2113 assert(pvStructInfo
);
2114 str
= *(LPWSTR
*)pvStructInfo
;
2115 for (i
= 0; i
< dataLen
/ 2; i
++)
2116 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
2117 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
2118 /* Decoded string is always NULL-terminated */
2125 static BOOL WINAPI
CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType
,
2126 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2127 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2132 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2133 pvStructInfo
, pvStructInfo
? *pcbStructInfo
: 0);
2135 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2137 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2139 ret
= CRYPT_AsnDecodeBMPString(dwCertEncodingType
, lpszStructType
,
2140 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pvStructInfo
,
2146 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
2147 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2148 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2152 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2153 pvStructInfo
, *pcbStructInfo
);
2157 struct AsnDecodeSequenceItem items
[] = {
2158 { ASN_CONSTRUCTOR
| ASN_CONTEXT
,
2159 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
),
2160 CRYPT_AsnDecodeProgramName
, sizeof(LPCWSTR
), TRUE
, TRUE
,
2161 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
), 0 },
2162 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
2163 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
),
2164 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2165 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
), 0 },
2166 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2,
2167 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
),
2168 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2169 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
), 0 },
2172 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2173 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2177 SetLastError(STATUS_ACCESS_VIOLATION
);
2180 TRACE("returning %d\n", ret
);
2184 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2185 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2186 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2187 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2192 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2194 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2196 if (dataLen
> sizeof(int))
2198 SetLastError(CRYPT_E_ASN1_LARGE
);
2201 else if (!pvStructInfo
)
2202 *pcbStructInfo
= sizeof(int);
2203 else if (*pcbStructInfo
< sizeof(int))
2205 *pcbStructInfo
= sizeof(int);
2206 SetLastError(ERROR_MORE_DATA
);
2214 *pcbStructInfo
= sizeof(int);
2215 if (dataLen
&& pbEncoded
[1 + lenBytes
] & 0x80)
2217 /* initialize to a negative value to sign-extend */
2222 for (i
= 0; i
< dataLen
; i
++)
2225 val
|= pbEncoded
[1 + lenBytes
+ i
];
2227 memcpy(pvStructInfo
, &val
, sizeof(int));
2233 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
2234 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2235 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2239 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2240 pvStructInfo
, *pcbStructInfo
);
2244 struct AsnDecodeSequenceItem items
[] = {
2245 { ASN_BMPSTRING
, offsetof(CAT_MEMBERINFO
, pwszSubjGuid
),
2246 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2247 offsetof(CAT_MEMBERINFO
, pwszSubjGuid
), 0 },
2248 { ASN_INTEGER
, offsetof(CAT_MEMBERINFO
, dwCertVersion
),
2249 CRYPT_AsnDecodeInt
, FINALMEMBERSIZE(CAT_MEMBERINFO
, dwCertVersion
),
2250 FALSE
, FALSE
, 0, 0 },
2253 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2254 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2258 SetLastError(STATUS_ACCESS_VIOLATION
);
2261 TRACE("returning %d\n", ret
);
2265 BOOL WINAPI
WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType
,
2266 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2267 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2271 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2272 pvStructInfo
, *pcbStructInfo
);
2276 struct AsnDecodeSequenceItem items
[] = {
2277 { ASN_BMPSTRING
, offsetof(CAT_NAMEVALUE
, pwszTag
),
2278 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2279 offsetof(CAT_NAMEVALUE
, pwszTag
), 0 },
2280 { ASN_INTEGER
, offsetof(CAT_NAMEVALUE
, fdwFlags
),
2281 CRYPT_AsnDecodeInt
, MEMBERSIZE(CAT_NAMEVALUE
, fdwFlags
, Value
),
2282 FALSE
, FALSE
, 0, 0 },
2283 { ASN_OCTETSTRING
, offsetof(CAT_NAMEVALUE
, Value
),
2284 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2285 offsetof(CAT_NAMEVALUE
, Value
.pbData
), 0 },
2288 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2289 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2293 SetLastError(STATUS_ACCESS_VIOLATION
);
2296 TRACE("returning %d\n", ret
);
2300 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2301 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2302 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2308 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2311 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2313 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2316 if (pbEncoded
[1] > 1)
2318 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2323 *pcbStructInfo
= sizeof(BOOL
);
2326 else if (*pcbStructInfo
< sizeof(BOOL
))
2328 *pcbStructInfo
= sizeof(BOOL
);
2329 SetLastError(ERROR_MORE_DATA
);
2334 *pcbStructInfo
= sizeof(BOOL
);
2335 *(BOOL
*)pvStructInfo
= pbEncoded
[2] != 0;
2338 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2342 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType
,
2343 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2344 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2348 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2349 pvStructInfo
, *pcbStructInfo
);
2353 struct AsnDecodeSequenceItem items
[] = {
2354 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fFinancialInfoAvailable
),
2355 CRYPT_AsnDecodeBool
, MEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2356 fFinancialInfoAvailable
, fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2357 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fMeetsCriteria
),
2358 CRYPT_AsnDecodeBool
, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2359 fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2362 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
, ARRAY_SIZE(items
),
2363 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
2367 SetLastError(STATUS_ACCESS_VIOLATION
);
2370 TRACE("returning %d\n", ret
);