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
21 #include "wintrust_priv.h"
25 #include <wine/exception.h>
27 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
29 #ifdef WORDS_BIGENDIAN
36 #define hton16(x) RtlUshortByteSwap(x)
37 #define n16toh(x) RtlUshortByteSwap(x)
41 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
42 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
43 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
45 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
47 DWORD bytesNeeded
, significantBytes
= 0;
55 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
56 temp
<<= 8, significantBytes
--)
58 bytesNeeded
= significantBytes
+ 1;
62 *pcbEncoded
= bytesNeeded
;
65 if (*pcbEncoded
< bytesNeeded
)
67 SetLastError(ERROR_MORE_DATA
);
71 *pbEncoded
= (BYTE
)len
;
76 *pbEncoded
++ = significantBytes
| 0x80;
77 for (i
= 0; i
< significantBytes
; i
++)
79 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
83 *pcbEncoded
= bytesNeeded
;
87 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
88 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
92 const CRYPT_DATA_BLOB
*blob
= pvStructInfo
;
93 DWORD bytesNeeded
, lenBytes
;
95 TRACE("(%d, %p), %p, %d\n", blob
->cbData
, blob
->pbData
, pbEncoded
,
98 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
99 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
101 *pcbEncoded
= bytesNeeded
;
102 else if (*pcbEncoded
< bytesNeeded
)
104 *pcbEncoded
= bytesNeeded
;
105 SetLastError(ERROR_MORE_DATA
);
110 *pbEncoded
++ = ASN_OCTETSTRING
;
111 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
112 pbEncoded
+= lenBytes
;
114 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
116 TRACE("returning %d\n", ret
);
120 BOOL WINAPI
WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType
,
121 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
126 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
127 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
132 const SPC_LINK
*link
= pvStructInfo
;
133 DWORD bytesNeeded
, lenBytes
;
135 switch (link
->dwLinkChoice
)
137 case SPC_FILE_LINK_CHOICE
:
139 DWORD fileNameLen
, fileNameLenBytes
;
142 fileNameLen
= link
->u
.pwszFile
?
143 lstrlenW(link
->u
.pwszFile
) * sizeof(WCHAR
) : 0;
144 CRYPT_EncodeLen(fileNameLen
, NULL
, &fileNameLenBytes
);
145 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, NULL
,
147 bytesNeeded
= 2 + lenBytes
+ fileNameLenBytes
+ fileNameLen
;
150 *pcbEncoded
= bytesNeeded
;
153 else if (*pcbEncoded
< bytesNeeded
)
155 SetLastError(ERROR_MORE_DATA
);
156 *pcbEncoded
= bytesNeeded
;
160 *pcbEncoded
= bytesNeeded
;
161 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2;
162 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, pbEncoded
,
164 pbEncoded
+= lenBytes
;
165 *pbEncoded
++ = ASN_CONTEXT
;
166 CRYPT_EncodeLen(fileNameLen
, pbEncoded
, &fileNameLenBytes
);
167 pbEncoded
+= fileNameLenBytes
;
168 for (ptr
= link
->u
.pwszFile
; ptr
&& *ptr
; ptr
++)
170 *(WCHAR
*)pbEncoded
= hton16(*ptr
);
171 pbEncoded
+= sizeof(WCHAR
);
177 case SPC_MONIKER_LINK_CHOICE
:
179 DWORD classIdLenBytes
, dataLenBytes
, dataLen
;
180 CRYPT_DATA_BLOB classId
= { sizeof(link
->u
.Moniker
.ClassId
),
181 (BYTE
*)link
->u
.Moniker
.ClassId
};
183 CRYPT_EncodeLen(classId
.cbData
, NULL
, &classIdLenBytes
);
184 CRYPT_EncodeLen(link
->u
.Moniker
.SerializedData
.cbData
, NULL
,
186 dataLen
= 2 + classIdLenBytes
+ classId
.cbData
+
187 dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
188 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
189 bytesNeeded
= 1 + dataLen
+ lenBytes
;
192 *pcbEncoded
= bytesNeeded
;
195 else if (*pcbEncoded
< bytesNeeded
)
197 SetLastError(ERROR_MORE_DATA
);
198 *pcbEncoded
= bytesNeeded
;
204 *pcbEncoded
= bytesNeeded
;
205 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
206 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
207 pbEncoded
+= lenBytes
;
208 size
= 1 + classIdLenBytes
+ classId
.cbData
;
209 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
, &classId
,
212 size
= 1 + dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
213 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
,
214 &link
->u
.Moniker
.SerializedData
, pbEncoded
, &size
);
220 case SPC_URL_LINK_CHOICE
:
225 /* Check for invalid characters in URL */
228 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
&& ret
; ptr
++)
232 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
239 CRYPT_EncodeLen(urlLen
, NULL
, &lenBytes
);
240 bytesNeeded
= 1 + lenBytes
+ urlLen
;
242 *pcbEncoded
= bytesNeeded
;
243 else if (*pcbEncoded
< bytesNeeded
)
245 SetLastError(ERROR_MORE_DATA
);
246 *pcbEncoded
= bytesNeeded
;
251 *pcbEncoded
= bytesNeeded
;
252 *pbEncoded
++ = ASN_CONTEXT
;
253 CRYPT_EncodeLen(urlLen
, pbEncoded
, &lenBytes
);
254 pbEncoded
+= lenBytes
;
255 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
; ptr
++)
256 *pbEncoded
++ = (BYTE
)*ptr
;
262 SetLastError(E_INVALIDARG
);
267 SetLastError(STATUS_ACCESS_VIOLATION
);
270 TRACE("returning %d\n", ret
);
274 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
277 struct AsnEncodeSequenceItem
279 const void *pvStructInfo
;
280 CryptEncodeObjectFunc encodeFunc
;
281 DWORD size
; /* used during encoding, not for your use */
284 static BOOL
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
285 struct AsnEncodeSequenceItem items
[], DWORD cItem
, BYTE
*pbEncoded
,
289 DWORD i
, dataLen
= 0;
291 TRACE("%p, %d, %p, %d\n", items
, cItem
, pbEncoded
, *pcbEncoded
);
292 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
294 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
295 items
[i
].pvStructInfo
, NULL
, &items
[i
].size
);
296 /* Some functions propagate their errors through the size */
298 *pcbEncoded
= items
[i
].size
;
299 dataLen
+= items
[i
].size
;
303 DWORD lenBytes
, bytesNeeded
;
305 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
306 bytesNeeded
= 1 + lenBytes
+ dataLen
;
308 *pcbEncoded
= bytesNeeded
;
309 else if (*pcbEncoded
< bytesNeeded
)
311 *pcbEncoded
= bytesNeeded
;
312 SetLastError(ERROR_MORE_DATA
);
317 *pcbEncoded
= bytesNeeded
;
318 *pbEncoded
++ = ASN_SEQUENCE
;
319 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
320 pbEncoded
+= lenBytes
;
321 for (i
= 0; ret
&& i
< cItem
; i
++)
323 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
324 items
[i
].pvStructInfo
, pbEncoded
, &items
[i
].size
);
325 /* Some functions propagate their errors through the size */
327 *pcbEncoded
= items
[i
].size
;
328 pbEncoded
+= items
[i
].size
;
332 TRACE("returning %d\n", ret
);
336 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
337 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
344 const CRYPT_BIT_BLOB
*blob
= pvStructInfo
;
345 DWORD bytesNeeded
, lenBytes
, dataBytes
;
348 /* yep, MS allows cUnusedBits to be >= 8 */
349 if (!blob
->cUnusedBits
)
351 dataBytes
= blob
->cbData
;
354 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
356 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
357 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
365 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
366 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
369 *pcbEncoded
= bytesNeeded
;
372 else if (*pcbEncoded
< bytesNeeded
)
374 *pcbEncoded
= bytesNeeded
;
375 SetLastError(ERROR_MORE_DATA
);
380 *pcbEncoded
= bytesNeeded
;
381 *pbEncoded
++ = ASN_BITSTRING
;
382 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
383 pbEncoded
+= lenBytes
;
384 *pbEncoded
++ = unusedBits
;
387 BYTE mask
= 0xff << unusedBits
;
391 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
392 pbEncoded
+= dataBytes
- 1;
394 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
400 SetLastError(STATUS_ACCESS_VIOLATION
);
406 struct AsnConstructedItem
409 const void *pvStructInfo
;
410 CryptEncodeObjectFunc encodeFunc
;
413 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
414 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
418 const struct AsnConstructedItem
*item
= pvStructInfo
;
421 if ((ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
422 item
->pvStructInfo
, NULL
, &len
)))
424 DWORD dataLen
, bytesNeeded
;
426 CRYPT_EncodeLen(len
, NULL
, &dataLen
);
427 bytesNeeded
= 1 + dataLen
+ len
;
429 *pcbEncoded
= bytesNeeded
;
430 else if (*pcbEncoded
< bytesNeeded
)
432 *pcbEncoded
= bytesNeeded
;
433 SetLastError(ERROR_MORE_DATA
);
438 *pcbEncoded
= bytesNeeded
;
439 *pbEncoded
++ = ASN_CONTEXT
| ASN_CONSTRUCTOR
| item
->tag
;
440 CRYPT_EncodeLen(len
, pbEncoded
, &dataLen
);
441 pbEncoded
+= dataLen
;
442 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
443 item
->pvStructInfo
, pbEncoded
, &len
);
446 /* Some functions propagate their errors through the size */
453 /* Some functions propagate their errors through the size */
460 BOOL WINAPI
WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType
,
461 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
464 const SPC_PE_IMAGE_DATA
*imageData
= pvStructInfo
;
467 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
468 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
473 struct AsnEncodeSequenceItem items
[2] = {
476 struct AsnConstructedItem constructed
= { 0, imageData
->pFile
,
477 WVTAsn1SpcLinkEncode
};
480 if (imageData
->Flags
.cbData
)
482 items
[cItem
].pvStructInfo
= &imageData
->Flags
;
483 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBits
;
486 if (imageData
->pFile
)
488 items
[cItem
].pvStructInfo
= &constructed
;
489 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
493 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
494 pbEncoded
, pcbEncoded
);
498 SetLastError(STATUS_ACCESS_VIOLATION
);
501 TRACE("returning %d\n", ret
);
505 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
506 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
509 LPCSTR pszObjId
= pvStructInfo
;
510 DWORD bytesNeeded
= 0, lenBytes
;
515 TRACE("%s\n", debugstr_a(pszObjId
));
522 if (sscanf(pszObjId
, "%d.%d%n", &val1
, &val2
, &firstPos
) != 2)
524 SetLastError(CRYPT_E_ASN1_ERROR
);
528 firstByte
= val1
* 40 + val2
;
529 ptr
= pszObjId
+ firstPos
;
539 /* note I assume each component is at most 32-bits long in base 2 */
540 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
542 if (val1
>= 0x10000000)
544 else if (val1
>= 0x200000)
546 else if (val1
>= 0x4000)
548 else if (val1
>= 0x80)
558 SetLastError(CRYPT_E_ASN1_ERROR
);
562 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
566 bytesNeeded
+= 1 + lenBytes
;
569 if (*pcbEncoded
< bytesNeeded
)
571 SetLastError(ERROR_MORE_DATA
);
576 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
577 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
578 pbEncoded
+= lenBytes
;
584 *pbEncoded
++ = firstByte
;
585 ptr
= pszObjId
+ firstPos
;
588 sscanf(ptr
, "%d%n", &val
, &pos
);
590 unsigned char outBytes
[5];
593 if (val
>= 0x10000000)
595 else if (val
>= 0x200000)
597 else if (val
>= 0x4000)
599 else if (val
>= 0x80)
603 for (i
= numBytes
; i
> 0; i
--)
605 outBytes
[i
- 1] = val
& 0x7f;
608 for (i
= 0; i
< numBytes
- 1; i
++)
609 *pbEncoded
++ = outBytes
[i
] | 0x80;
610 *pbEncoded
++ = outBytes
[i
];
619 *pcbEncoded
= bytesNeeded
;
623 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
624 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
627 const CRYPT_DER_BLOB
*blob
= pvStructInfo
;
631 *pcbEncoded
= blob
->cbData
;
632 else if (*pcbEncoded
< blob
->cbData
)
634 *pcbEncoded
= blob
->cbData
;
635 SetLastError(ERROR_MORE_DATA
);
641 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
642 *pcbEncoded
= blob
->cbData
;
647 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
648 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
649 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
651 const CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
652 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
653 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
656 struct AsnEncodeSequenceItem items
[2] = {
657 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
658 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
661 if (algo
->Parameters
.cbData
)
662 items
[1].pvStructInfo
= &algo
->Parameters
;
664 items
[1].pvStructInfo
= &nullBlob
;
665 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
666 sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
670 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
671 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
674 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
675 struct AsnEncodeSequenceItem items
[] = {
676 { &typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
677 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
680 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
681 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
686 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
687 CRYPT_HASH_BLOB Digest
;
690 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
691 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
694 const struct SPCDigest
*digest
= pvStructInfo
;
695 struct AsnEncodeSequenceItem items
[] = {
696 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
697 { &digest
->Digest
, CRYPT_CopyEncodedBlob
, 0 },
700 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
701 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
704 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
705 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
710 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
711 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
715 const SPC_INDIRECT_DATA_CONTENT
*data
= pvStructInfo
;
716 struct AsnEncodeSequenceItem items
[] = {
717 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
718 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
721 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
722 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
726 SetLastError(STATUS_ACCESS_VIOLATION
);
732 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
733 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
737 LPCWSTR str
= pvStructInfo
;
738 DWORD bytesNeeded
, lenBytes
, strLen
;
741 strLen
= lstrlenW(str
);
744 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
745 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
747 *pcbEncoded
= bytesNeeded
;
748 else if (*pcbEncoded
< bytesNeeded
)
750 *pcbEncoded
= bytesNeeded
;
751 SetLastError(ERROR_MORE_DATA
);
758 *pcbEncoded
= bytesNeeded
;
759 *pbEncoded
++ = ASN_BMPSTRING
;
760 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
761 pbEncoded
+= lenBytes
;
762 for (i
= 0; i
< strLen
; i
++)
764 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
765 *pbEncoded
++ = str
[i
] & 0x00ff;
771 struct AsnEncodeTagSwappedItem
774 const void *pvStructInfo
;
775 CryptEncodeObjectFunc encodeFunc
;
778 /* Sort of a wacky hack, it encodes something using the struct
779 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
780 * given in the struct AsnEncodeTagSwappedItem.
782 static BOOL WINAPI
CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType
,
783 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
787 const struct AsnEncodeTagSwappedItem
*item
= pvStructInfo
;
789 ret
= item
->encodeFunc(dwCertEncodingType
, lpszStructType
,
790 item
->pvStructInfo
, pbEncoded
, pcbEncoded
);
791 if (ret
&& pbEncoded
)
792 *pbEncoded
= item
->tag
;
796 BOOL WINAPI
WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType
,
797 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
802 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
803 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
807 const SPC_SP_OPUS_INFO
*info
= pvStructInfo
;
809 if (info
->pMoreInfo
&&
810 info
->pMoreInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
811 info
->pMoreInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
812 info
->pMoreInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
813 SetLastError(E_INVALIDARG
);
814 else if (info
->pPublisherInfo
&&
815 info
->pPublisherInfo
->dwLinkChoice
!= SPC_URL_LINK_CHOICE
&&
816 info
->pPublisherInfo
->dwLinkChoice
!= SPC_MONIKER_LINK_CHOICE
&&
817 info
->pPublisherInfo
->dwLinkChoice
!= SPC_FILE_LINK_CHOICE
)
818 SetLastError(E_INVALIDARG
);
821 struct AsnEncodeSequenceItem items
[3] = { { 0 } };
822 struct AsnConstructedItem constructed
[3] = { { 0 } };
823 struct AsnEncodeTagSwappedItem swapped
;
824 DWORD cItem
= 0, cConstructed
= 0;
826 if (info
->pwszProgramName
)
828 swapped
.tag
= ASN_CONTEXT
;
829 swapped
.pvStructInfo
= info
->pwszProgramName
;
830 swapped
.encodeFunc
= CRYPT_AsnEncodeBMPString
;
831 constructed
[cConstructed
].tag
= 0;
832 constructed
[cConstructed
].pvStructInfo
= &swapped
;
833 constructed
[cConstructed
].encodeFunc
= CRYPT_AsnEncodeSwapTag
;
834 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
835 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
841 constructed
[cConstructed
].tag
= 1;
842 constructed
[cConstructed
].pvStructInfo
= info
->pMoreInfo
;
843 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
844 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
845 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
849 if (info
->pPublisherInfo
)
851 constructed
[cConstructed
].tag
= 2;
852 constructed
[cConstructed
].pvStructInfo
= info
->pPublisherInfo
;
853 constructed
[cConstructed
].encodeFunc
= WVTAsn1SpcLinkEncode
;
854 items
[cItem
].pvStructInfo
= &constructed
[cConstructed
];
855 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
859 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
860 items
, cItem
, pbEncoded
, pcbEncoded
);
865 SetLastError(STATUS_ACCESS_VIOLATION
);
871 static BOOL
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
872 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
879 DWORD significantBytes
, lenBytes
, bytesNeeded
;
882 const CRYPT_INTEGER_BLOB
*blob
= pvStructInfo
;
884 significantBytes
= blob
->cbData
;
885 if (significantBytes
)
887 if (blob
->pbData
[significantBytes
- 1] & 0x80)
889 /* negative, lop off leading (little-endian) 0xffs */
890 for (; significantBytes
> 0 &&
891 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
893 if (blob
->pbData
[significantBytes
- 1] < 0x80)
901 /* positive, lop off leading (little-endian) zeroes */
902 for (; significantBytes
> 0 &&
903 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
905 if (significantBytes
== 0)
906 significantBytes
= 1;
907 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
915 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
917 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
918 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
923 *pcbEncoded
= bytesNeeded
;
926 else if (*pcbEncoded
< bytesNeeded
)
928 *pcbEncoded
= bytesNeeded
;
929 SetLastError(ERROR_MORE_DATA
);
934 *pcbEncoded
= bytesNeeded
;
935 *pbEncoded
++ = ASN_INTEGER
;
938 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
939 pbEncoded
+= lenBytes
;
940 *pbEncoded
++ = padByte
;
944 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
945 pbEncoded
+= lenBytes
;
947 for (; significantBytes
> 0; significantBytes
--)
948 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
954 SetLastError(STATUS_ACCESS_VIOLATION
);
961 static BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
962 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
965 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
967 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
968 &blob
, pbEncoded
, pcbEncoded
);
971 BOOL WINAPI
WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType
,
972 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
977 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
978 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
982 const CAT_MEMBERINFO
*info
= pvStructInfo
;
983 struct AsnEncodeSequenceItem items
[] = {
984 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
985 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
988 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
989 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
993 SetLastError(STATUS_ACCESS_VIOLATION
);
999 BOOL WINAPI
WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType
,
1000 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1005 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1006 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1010 const CAT_NAMEVALUE
*value
= pvStructInfo
;
1011 struct AsnEncodeSequenceItem items
[] = {
1012 { value
->pwszTag
, CRYPT_AsnEncodeBMPString
, 0 },
1013 { &value
->fdwFlags
, CRYPT_AsnEncodeInt
, 0 },
1014 { &value
->Value
, CRYPT_AsnEncodeOctets
, 0 },
1017 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1018 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1022 SetLastError(STATUS_ACCESS_VIOLATION
);
1028 static BOOL WINAPI
CRYPT_AsnEncodeBool(DWORD dwCertEncodingType
,
1029 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1032 BOOL val
= *(const BOOL
*)pvStructInfo
, ret
;
1041 else if (*pcbEncoded
< 3)
1044 SetLastError(ERROR_MORE_DATA
);
1050 *pbEncoded
++ = ASN_BOOL
;
1052 *pbEncoded
++ = val
? 0xff : 0;
1055 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1059 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType
,
1060 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
1065 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
1066 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
1070 const SPC_FINANCIAL_CRITERIA
*criteria
= pvStructInfo
;
1071 struct AsnEncodeSequenceItem items
[] = {
1072 { &criteria
->fFinancialInfoAvailable
, CRYPT_AsnEncodeBool
, 0 },
1073 { &criteria
->fMeetsCriteria
, CRYPT_AsnEncodeBool
, 0 },
1076 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
1077 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
1081 SetLastError(STATUS_ACCESS_VIOLATION
);
1087 /* Gets the number of length bytes from the given (leading) length byte */
1088 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1090 /* Helper function to get the encoded length of the data starting at pbEncoded,
1091 * where pbEncoded[0] is the tag. If the data are too short to contain a
1092 * length or if the length is too large for cbEncoded, sets an appropriate
1093 * error code and returns FALSE.
1095 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
1101 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1104 else if (pbEncoded
[1] <= 0x7f)
1106 if (pbEncoded
[1] + 1 > cbEncoded
)
1108 SetLastError(CRYPT_E_ASN1_EOD
);
1113 *len
= pbEncoded
[1];
1117 else if (pbEncoded
[1] == 0x80)
1119 FIXME("unimplemented for indefinite-length encoding\n");
1120 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1125 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
1127 if (lenLen
> sizeof(DWORD
) + 1)
1129 SetLastError(CRYPT_E_ASN1_LARGE
);
1132 else if (lenLen
+ 2 > cbEncoded
)
1134 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1145 out
|= *pbEncoded
++;
1147 if (out
+ lenLen
+ 1 > cbEncoded
)
1149 SetLastError(CRYPT_E_ASN1_EOD
);
1162 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
1163 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1164 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1167 DWORD bytesNeeded
, dataLen
;
1169 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1170 pvStructInfo
, *pcbStructInfo
);
1174 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1177 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
1179 SetLastError(CRYPT_E_ASN1_BADTAG
);
1182 else if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1184 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1185 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
1187 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
1189 *pcbStructInfo
= bytesNeeded
;
1190 else if (*pcbStructInfo
< bytesNeeded
)
1192 SetLastError(ERROR_MORE_DATA
);
1193 *pcbStructInfo
= bytesNeeded
;
1198 CRYPT_DATA_BLOB
*blob
;
1199 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1201 blob
= pvStructInfo
;
1202 blob
->cbData
= dataLen
;
1203 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1204 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
1207 assert(blob
->pbData
);
1209 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
1217 static BOOL
CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType
,
1218 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1219 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1222 DWORD bytesNeeded
= sizeof(SPC_LINK
), dataLen
;
1224 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1225 pvStructInfo
, *pcbStructInfo
);
1227 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1229 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1232 switch (pbEncoded
[0])
1235 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
1237 *pcbStructInfo
= bytesNeeded
;
1238 else if (*pcbStructInfo
< bytesNeeded
)
1240 *pcbStructInfo
= bytesNeeded
;
1241 SetLastError(ERROR_MORE_DATA
);
1246 PSPC_LINK link
= pvStructInfo
;
1249 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1250 for (i
= 0; i
< dataLen
; i
++)
1251 link
->u
.pwszUrl
[i
] =
1252 *(pbEncoded
+ 1 + lenBytes
+ i
);
1253 link
->u
.pwszUrl
[i
] = '\0';
1254 TRACE("returning url %s\n", debugstr_w(link
->u
.pwszUrl
));
1257 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1:
1259 CRYPT_DATA_BLOB classId
;
1260 DWORD size
= sizeof(classId
);
1262 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1263 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
1264 CRYPT_DECODE_NOCOPY_FLAG
, &classId
, &size
)))
1266 if (classId
.cbData
!= sizeof(SPC_UUID
))
1268 SetLastError(CRYPT_E_BAD_ENCODE
);
1273 CRYPT_DATA_BLOB data
;
1275 /* The tag length for the classId must be 1 since the
1276 * length is correct.
1278 size
= sizeof(data
);
1279 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1280 pbEncoded
+ 3 + lenBytes
+ classId
.cbData
,
1281 cbEncoded
- 3 - lenBytes
- classId
.cbData
,
1282 CRYPT_DECODE_NOCOPY_FLAG
, &data
, &size
)))
1284 bytesNeeded
+= data
.cbData
;
1286 *pcbStructInfo
= bytesNeeded
;
1287 else if (*pcbStructInfo
< bytesNeeded
)
1289 *pcbStructInfo
= bytesNeeded
;
1290 SetLastError(ERROR_MORE_DATA
);
1295 PSPC_LINK link
= pvStructInfo
;
1297 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1298 /* pwszFile pointer was set by caller, copy it
1299 * before overwriting it
1301 link
->u
.Moniker
.SerializedData
.pbData
=
1302 (BYTE
*)link
->u
.pwszFile
;
1303 memcpy(link
->u
.Moniker
.ClassId
, classId
.pbData
,
1305 memcpy(link
->u
.Moniker
.SerializedData
.pbData
,
1306 data
.pbData
, data
.cbData
);
1307 link
->u
.Moniker
.SerializedData
.cbData
= data
.cbData
;
1314 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2:
1315 if (dataLen
&& pbEncoded
[1 + lenBytes
] != ASN_CONTEXT
)
1316 SetLastError(CRYPT_E_ASN1_BADTAG
);
1317 else if ((ret
= CRYPT_GetLen(pbEncoded
+ 1 + lenBytes
, dataLen
,
1320 BYTE realLenBytes
= GET_LEN_BYTES(pbEncoded
[2 + lenBytes
]);
1322 bytesNeeded
+= realDataLen
+ sizeof(WCHAR
);
1324 *pcbStructInfo
= bytesNeeded
;
1325 else if (*pcbStructInfo
< bytesNeeded
)
1327 *pcbStructInfo
= bytesNeeded
;
1328 SetLastError(ERROR_MORE_DATA
);
1333 PSPC_LINK link
= pvStructInfo
;
1335 const BYTE
*ptr
= pbEncoded
+ 2 + lenBytes
+ realLenBytes
;
1337 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1338 for (i
= 0; i
< dataLen
/ sizeof(WCHAR
); i
++)
1339 link
->u
.pwszFile
[i
] =
1340 hton16(*(const WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1341 link
->u
.pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1342 TRACE("returning file %s\n", debugstr_w(link
->u
.pwszFile
));
1347 bytesNeeded
+= sizeof(WCHAR
);
1349 *pcbStructInfo
= bytesNeeded
;
1350 else if (*pcbStructInfo
< bytesNeeded
)
1352 *pcbStructInfo
= bytesNeeded
;
1353 SetLastError(ERROR_MORE_DATA
);
1358 PSPC_LINK link
= pvStructInfo
;
1360 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1361 link
->u
.pwszFile
[0] = '\0';
1367 SetLastError(CRYPT_E_ASN1_BADTAG
);
1370 TRACE("returning %d\n", ret
);
1374 BOOL WINAPI
WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType
,
1375 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1376 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1380 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1381 pvStructInfo
, *pcbStructInfo
);
1387 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1388 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, NULL
, &bytesNeeded
);
1392 *pcbStructInfo
= bytesNeeded
;
1393 else if (*pcbStructInfo
< bytesNeeded
)
1395 *pcbStructInfo
= bytesNeeded
;
1396 SetLastError(ERROR_MORE_DATA
);
1401 SPC_LINK
*link
= pvStructInfo
;
1404 (LPWSTR
)((BYTE
*)pvStructInfo
+ sizeof(SPC_LINK
));
1405 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1406 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1413 SetLastError(STATUS_ACCESS_VIOLATION
);
1416 TRACE("returning %d\n", ret
);
1420 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1421 DWORD
, DWORD
, void *, DWORD
*);
1424 * The expected tag of the item. If tag is 0, decodeFunc is called
1425 * regardless of the tag value seen.
1427 * A sequence is decoded into a struct. The offset member is the
1428 * offset of this item within that struct.
1430 * The decoder function to use. If this is NULL, then the member isn't
1431 * decoded, but minSize space is reserved for it.
1433 * The minimum amount of space occupied after decoding. You must set this.
1435 * If true, and the tag doesn't match the expected tag for this item,
1436 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1437 * filled with 0 for this member.
1438 * hasPointer, pointerOffset:
1439 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1440 * the offset within the struct of the data pointer (or to the
1441 * first data pointer, if more than one exist).
1443 * Used by CRYPT_AsnDecodeSequence, not for your use.
1445 struct AsnDecodeSequenceItem
1449 CryptDecodeObjectFunc decodeFunc
;
1453 DWORD pointerOffset
;
1457 /* Align up to a DWORD_PTR boundary
1459 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1))
1461 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
1462 #define MEMBERSIZE(s, member, nextmember) \
1463 (offsetof(s, nextmember) - offsetof(s, member))
1466 /* Decodes the items in a sequence, where the items are described in items,
1467 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1468 * pvStructInfo. nextData is a pointer to the memory location at which the
1469 * first decoded item with a dynamic pointer should point.
1470 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1472 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
1473 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1474 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
1478 DWORD i
, decoded
= 0;
1479 const BYTE
*ptr
= pbEncoded
;
1481 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
1482 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
1484 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
1486 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
1490 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
1493 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
1495 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
1497 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
1499 TRACE("Setting next pointer to %p\n",
1501 *(BYTE
**)((BYTE
*)pvStructInfo
+
1502 items
[i
].pointerOffset
) = nextData
;
1504 if (items
[i
].decodeFunc
)
1507 TRACE("decoding item %d\n", i
);
1509 TRACE("sizing item %d\n", i
);
1510 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
1511 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
1512 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
1513 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
1514 : NULL
, &items
[i
].size
);
1517 if (items
[i
].size
< items
[i
].minSize
)
1518 items
[i
].size
= items
[i
].minSize
;
1519 else if (items
[i
].size
> items
[i
].minSize
)
1521 /* Account for alignment padding */
1522 items
[i
].size
= ALIGN_DWORD_PTR(items
[i
].size
);
1524 TRACE("item %d size: %d\n", i
, items
[i
].size
);
1525 if (nextData
&& items
[i
].hasPointer
&&
1526 items
[i
].size
> items
[i
].minSize
)
1527 nextData
+= items
[i
].size
- items
[i
].minSize
;
1528 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1529 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1530 TRACE("item %d: decoded %d bytes\n", i
,
1531 1 + nextItemLenBytes
+ nextItemLen
);
1533 else if (items
[i
].optional
&&
1534 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1536 TRACE("skipping optional item %d\n", i
);
1537 items
[i
].size
= items
[i
].minSize
;
1538 SetLastError(NOERROR
);
1542 TRACE("item %d failed: %08x\n", i
,
1547 TRACE("item %d: decoded %d bytes\n", i
,
1548 1 + nextItemLenBytes
+ nextItemLen
);
1549 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1550 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1551 items
[i
].size
= items
[i
].minSize
;
1554 else if (items
[i
].optional
)
1556 TRACE("skipping optional item %d\n", i
);
1557 items
[i
].size
= items
[i
].minSize
;
1561 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1562 i
, ptr
[0], items
[i
].tag
);
1563 SetLastError(CRYPT_E_ASN1_BADTAG
);
1568 else if (items
[i
].optional
)
1570 TRACE("missing optional item %d, skipping\n", i
);
1571 items
[i
].size
= items
[i
].minSize
;
1575 TRACE("not enough bytes for item %d, failing\n", i
);
1576 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1581 *cbDecoded
= decoded
;
1582 TRACE("returning %d\n", ret
);
1586 /* This decodes an arbitrary sequence into a contiguous block of memory
1587 * (basically, a struct.) Each element being decoded is described by a struct
1588 * AsnDecodeSequenceItem, see above.
1589 * startingPointer is an optional pointer to the first place where dynamic
1590 * data will be stored. If you know the starting offset, you may pass it
1591 * here. Otherwise, pass NULL, and one will be inferred from the items.
1593 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1594 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1595 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1596 void *startingPointer
)
1600 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items
, cItem
, pbEncoded
,
1601 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1603 if (pbEncoded
[0] == ASN_SEQUENCE
)
1607 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1609 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1610 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1612 cbEncoded
-= 1 + lenBytes
;
1613 if (cbEncoded
< dataLen
)
1615 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
1617 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1621 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1622 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1623 if (ret
&& cbDecoded
!= dataLen
)
1625 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
1627 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1632 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1634 for (i
= 0; i
< cItem
; i
++)
1636 bytesNeeded
+= items
[i
].size
;
1637 structSize
+= items
[i
].minSize
;
1640 *pcbStructInfo
= bytesNeeded
;
1641 else if (*pcbStructInfo
< bytesNeeded
)
1643 SetLastError(ERROR_MORE_DATA
);
1644 *pcbStructInfo
= bytesNeeded
;
1651 *pcbStructInfo
= bytesNeeded
;
1652 if (startingPointer
)
1653 nextData
= startingPointer
;
1655 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1656 memset(pvStructInfo
, 0, structSize
);
1657 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1658 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1666 SetLastError(CRYPT_E_ASN1_BADTAG
);
1669 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1673 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1674 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1675 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1679 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
1680 pvStructInfo
, *pcbStructInfo
);
1682 if (pbEncoded
[0] == ASN_BITSTRING
)
1684 DWORD bytesNeeded
, dataLen
;
1686 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1688 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1689 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1691 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1693 *pcbStructInfo
= bytesNeeded
;
1694 else if (*pcbStructInfo
< bytesNeeded
)
1696 *pcbStructInfo
= bytesNeeded
;
1697 SetLastError(ERROR_MORE_DATA
);
1702 CRYPT_BIT_BLOB
*blob
;
1704 blob
= pvStructInfo
;
1705 blob
->cbData
= dataLen
- 1;
1706 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1707 GET_LEN_BYTES(pbEncoded
[1]));
1708 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1710 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1711 GET_LEN_BYTES(pbEncoded
[1]);
1715 assert(blob
->pbData
);
1718 BYTE mask
= 0xff << blob
->cUnusedBits
;
1720 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1721 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1722 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1730 SetLastError(CRYPT_E_ASN1_BADTAG
);
1733 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1737 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1738 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1739 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1744 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1746 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1748 SPC_LINK
**pLink
= pvStructInfo
;
1750 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1751 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1755 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1756 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1758 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1759 SetLastError(ERROR_MORE_DATA
);
1764 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1765 /* Set imageData's pointer if necessary */
1766 if (size
> sizeof(SPC_LINK
))
1768 (*pLink
)->u
.pwszUrl
=
1769 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1771 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1772 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1773 *pLink
, pcbStructInfo
);
1780 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1781 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1782 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1786 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1787 pvStructInfo
, *pcbStructInfo
);
1791 struct AsnDecodeSequenceItem items
[] = {
1792 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1793 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1794 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1795 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1796 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1797 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1800 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1801 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1802 pvStructInfo
, pcbStructInfo
, NULL
);
1806 SetLastError(STATUS_ACCESS_VIOLATION
);
1809 TRACE("returning %d\n", ret
);
1813 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1814 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1815 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1820 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1821 pvStructInfo
, *pcbStructInfo
);
1823 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1825 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1826 DWORD bytesNeeded
= sizeof(LPSTR
);
1830 /* The largest possible string for the first two components
1831 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1836 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1837 pbEncoded
[1 + lenBytes
] / 40,
1838 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1840 bytesNeeded
+= strlen(firstTwo
) + 1;
1841 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1842 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1844 /* large enough for ".4000000" */
1848 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1855 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1858 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1865 snprintf(str
, sizeof(str
), ".%d", val
);
1866 bytesNeeded
+= strlen(str
);
1871 *pcbStructInfo
= bytesNeeded
;
1872 else if (*pcbStructInfo
< bytesNeeded
)
1874 *pcbStructInfo
= bytesNeeded
;
1875 SetLastError(ERROR_MORE_DATA
);
1883 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1886 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1887 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1889 pszObjId
+= strlen(pszObjId
);
1890 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1891 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1895 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1904 sprintf(pszObjId
, ".%d", val
);
1905 pszObjId
+= strlen(pszObjId
);
1909 *(LPSTR
*)pvStructInfo
= NULL
;
1910 *pcbStructInfo
= bytesNeeded
;
1916 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1917 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1918 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1922 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1923 pvStructInfo
, *pcbStructInfo
);
1926 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1927 else if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1928 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1929 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1931 SetLastError(CRYPT_E_ASN1_BADTAG
);
1935 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1936 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1937 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1940 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1942 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1943 pvStructInfo
, *pcbStructInfo
);
1945 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1946 bytesNeeded
+= cbEncoded
;
1948 *pcbStructInfo
= bytesNeeded
;
1949 else if (*pcbStructInfo
< bytesNeeded
)
1951 SetLastError(ERROR_MORE_DATA
);
1952 *pcbStructInfo
= bytesNeeded
;
1957 PCRYPT_OBJID_BLOB blob
= pvStructInfo
;
1959 *pcbStructInfo
= bytesNeeded
;
1960 blob
->cbData
= cbEncoded
;
1961 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1962 blob
->pbData
= (LPBYTE
)pbEncoded
;
1965 assert(blob
->pbData
);
1966 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1972 static BOOL WINAPI
CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType
,
1973 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1974 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1976 CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
= pvStructInfo
;
1977 struct AsnDecodeSequenceItem items
[] = {
1978 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1979 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1980 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1981 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1982 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1983 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1986 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1987 pvStructInfo
, *pcbStructInfo
);
1989 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1990 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1991 pvStructInfo
, pcbStructInfo
,
1992 typeValue
? typeValue
->pszObjId
: NULL
);
1995 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
1996 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1997 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1999 CRYPT_ALGORITHM_IDENTIFIER
*algo
= pvStructInfo
;
2001 struct AsnDecodeSequenceItem items
[] = {
2002 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2003 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2004 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2005 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2006 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2007 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2010 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2011 pvStructInfo
, *pcbStructInfo
);
2013 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2014 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2015 pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2016 if (ret
&& pvStructInfo
)
2018 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2019 debugstr_a(algo
->pszObjId
));
2024 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
2025 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2026 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2028 struct SPCDigest
*digest
= pvStructInfo
;
2029 struct AsnDecodeSequenceItem items
[] = {
2030 { ASN_SEQUENCEOF
, offsetof(struct SPCDigest
, DigestAlgorithm
),
2031 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2033 offsetof(struct SPCDigest
, DigestAlgorithm
.pszObjId
), 0 },
2034 { ASN_OCTETSTRING
, offsetof(struct SPCDigest
, Digest
),
2035 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
),
2036 FALSE
, TRUE
, offsetof(struct SPCDigest
, Digest
.pbData
), 0 },
2039 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2040 pvStructInfo
, *pcbStructInfo
);
2042 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2043 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2044 pvStructInfo
, pcbStructInfo
,
2045 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
2048 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
2049 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2050 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2054 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2055 pvStructInfo
, *pcbStructInfo
);
2059 struct AsnDecodeSequenceItem items
[] = {
2060 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
2061 CRYPT_AsnDecodeAttributeTypeValue
,
2062 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
2063 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
2064 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
2065 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
2067 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
2070 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2071 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2072 pvStructInfo
, pcbStructInfo
, NULL
);
2076 SetLastError(STATUS_ACCESS_VIOLATION
);
2079 TRACE("returning %d\n", ret
);
2083 static BOOL WINAPI
CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType
,
2084 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2085 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2088 DWORD bytesNeeded
, dataLen
;
2090 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2092 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2094 bytesNeeded
= dataLen
+ 2 + sizeof(LPWSTR
);
2096 *pcbStructInfo
= bytesNeeded
;
2097 else if (*pcbStructInfo
< bytesNeeded
)
2099 *pcbStructInfo
= bytesNeeded
;
2100 SetLastError(ERROR_MORE_DATA
);
2108 *pcbStructInfo
= bytesNeeded
;
2109 assert(pvStructInfo
);
2110 str
= *(LPWSTR
*)pvStructInfo
;
2111 for (i
= 0; i
< dataLen
/ 2; i
++)
2112 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
2113 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
2114 /* Decoded string is always NULL-terminated */
2121 static BOOL WINAPI
CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType
,
2122 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2123 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2128 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2129 pvStructInfo
, pvStructInfo
? *pcbStructInfo
: 0);
2131 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2133 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2135 ret
= CRYPT_AsnDecodeBMPString(dwCertEncodingType
, lpszStructType
,
2136 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pvStructInfo
,
2142 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
2143 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2144 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2148 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2149 pvStructInfo
, *pcbStructInfo
);
2153 struct AsnDecodeSequenceItem items
[] = {
2154 { ASN_CONSTRUCTOR
| ASN_CONTEXT
,
2155 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
),
2156 CRYPT_AsnDecodeProgramName
, sizeof(LPCWSTR
), TRUE
, TRUE
,
2157 offsetof(SPC_SP_OPUS_INFO
, pwszProgramName
), 0 },
2158 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
2159 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
),
2160 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2161 offsetof(SPC_SP_OPUS_INFO
, pMoreInfo
), 0 },
2162 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2,
2163 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
),
2164 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
2165 offsetof(SPC_SP_OPUS_INFO
, pPublisherInfo
), 0 },
2168 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2169 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2170 pvStructInfo
, pcbStructInfo
, NULL
);
2174 SetLastError(STATUS_ACCESS_VIOLATION
);
2177 TRACE("returning %d\n", ret
);
2181 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2182 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2183 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2184 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2189 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2191 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2193 if (dataLen
> sizeof(int))
2195 SetLastError(CRYPT_E_ASN1_LARGE
);
2198 else if (!pvStructInfo
)
2199 *pcbStructInfo
= sizeof(int);
2200 else if (*pcbStructInfo
< sizeof(int))
2202 *pcbStructInfo
= sizeof(int);
2203 SetLastError(ERROR_MORE_DATA
);
2211 *pcbStructInfo
= sizeof(int);
2212 if (dataLen
&& pbEncoded
[1 + lenBytes
] & 0x80)
2214 /* initialize to a negative value to sign-extend */
2219 for (i
= 0; i
< dataLen
; i
++)
2222 val
|= pbEncoded
[1 + lenBytes
+ i
];
2224 memcpy(pvStructInfo
, &val
, sizeof(int));
2230 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
2231 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2232 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2236 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2237 pvStructInfo
, *pcbStructInfo
);
2241 struct AsnDecodeSequenceItem items
[] = {
2242 { ASN_BMPSTRING
, offsetof(CAT_MEMBERINFO
, pwszSubjGuid
),
2243 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2244 offsetof(CAT_MEMBERINFO
, pwszSubjGuid
), 0 },
2245 { ASN_INTEGER
, offsetof(CAT_MEMBERINFO
, dwCertVersion
),
2246 CRYPT_AsnDecodeInt
, FINALMEMBERSIZE(CAT_MEMBERINFO
, dwCertVersion
),
2247 FALSE
, FALSE
, 0, 0 },
2250 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2251 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2252 pvStructInfo
, pcbStructInfo
, NULL
);
2256 SetLastError(STATUS_ACCESS_VIOLATION
);
2259 TRACE("returning %d\n", ret
);
2263 BOOL WINAPI
WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType
,
2264 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2265 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2269 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2270 pvStructInfo
, *pcbStructInfo
);
2274 struct AsnDecodeSequenceItem items
[] = {
2275 { ASN_BMPSTRING
, offsetof(CAT_NAMEVALUE
, pwszTag
),
2276 CRYPT_AsnDecodeBMPString
, sizeof(LPWSTR
), FALSE
, TRUE
,
2277 offsetof(CAT_NAMEVALUE
, pwszTag
), 0 },
2278 { ASN_INTEGER
, offsetof(CAT_NAMEVALUE
, fdwFlags
),
2279 CRYPT_AsnDecodeInt
, MEMBERSIZE(CAT_NAMEVALUE
, fdwFlags
, Value
),
2280 FALSE
, FALSE
, 0, 0 },
2281 { ASN_OCTETSTRING
, offsetof(CAT_NAMEVALUE
, Value
),
2282 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
2283 offsetof(CAT_NAMEVALUE
, Value
.pbData
), 0 },
2286 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2287 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2288 pvStructInfo
, pcbStructInfo
, NULL
);
2292 SetLastError(STATUS_ACCESS_VIOLATION
);
2295 TRACE("returning %d\n", ret
);
2299 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2300 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2301 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2307 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2310 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2312 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2315 if (pbEncoded
[1] > 1)
2317 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2322 *pcbStructInfo
= sizeof(BOOL
);
2325 else if (*pcbStructInfo
< sizeof(BOOL
))
2327 *pcbStructInfo
= sizeof(BOOL
);
2328 SetLastError(ERROR_MORE_DATA
);
2333 *pcbStructInfo
= sizeof(BOOL
);
2334 *(BOOL
*)pvStructInfo
= pbEncoded
[2] != 0;
2337 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2341 BOOL WINAPI
WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType
,
2342 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2343 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2347 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2348 pvStructInfo
, *pcbStructInfo
);
2352 struct AsnDecodeSequenceItem items
[] = {
2353 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fFinancialInfoAvailable
),
2354 CRYPT_AsnDecodeBool
, MEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2355 fFinancialInfoAvailable
, fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2356 { ASN_BOOL
, offsetof(SPC_FINANCIAL_CRITERIA
, fMeetsCriteria
),
2357 CRYPT_AsnDecodeBool
, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA
,
2358 fMeetsCriteria
), FALSE
, FALSE
, 0, 0 },
2361 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2362 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2363 pvStructInfo
, pcbStructInfo
, NULL
);
2367 SetLastError(STATUS_ACCESS_VIOLATION
);
2370 TRACE("returning %d\n", ret
);