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_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
53 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
55 static BOOL
CRYPT_EncodeLen(DWORD len
, BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
57 DWORD bytesNeeded
, significantBytes
= 0;
65 for (temp
= len
, significantBytes
= sizeof(temp
); !(temp
& 0xff000000);
66 temp
<<= 8, significantBytes
--)
68 bytesNeeded
= significantBytes
+ 1;
72 *pcbEncoded
= bytesNeeded
;
75 if (*pcbEncoded
< bytesNeeded
)
77 SetLastError(ERROR_MORE_DATA
);
81 *pbEncoded
= (BYTE
)len
;
86 *pbEncoded
++ = significantBytes
| 0x80;
87 for (i
= 0; i
< significantBytes
; i
++)
89 *(pbEncoded
+ significantBytes
- i
- 1) = (BYTE
)(len
& 0xff);
93 *pcbEncoded
= bytesNeeded
;
97 static BOOL WINAPI
CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
102 const CRYPT_DATA_BLOB
*blob
= (const CRYPT_DATA_BLOB
*)pvStructInfo
;
103 DWORD bytesNeeded
, lenBytes
;
105 TRACE("(%d, %p), %p, %d\n", blob
->cbData
, blob
->pbData
, pbEncoded
,
108 CRYPT_EncodeLen(blob
->cbData
, NULL
, &lenBytes
);
109 bytesNeeded
= 1 + lenBytes
+ blob
->cbData
;
111 *pcbEncoded
= bytesNeeded
;
112 else if (*pcbEncoded
< bytesNeeded
)
114 *pcbEncoded
= bytesNeeded
;
115 SetLastError(ERROR_MORE_DATA
);
120 *pbEncoded
++ = ASN_OCTETSTRING
;
121 CRYPT_EncodeLen(blob
->cbData
, pbEncoded
, &lenBytes
);
122 pbEncoded
+= lenBytes
;
124 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
126 TRACE("returning %d\n", ret
);
130 BOOL WINAPI
WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType
,
131 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
136 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
137 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
142 const SPC_LINK
*link
= (const SPC_LINK
*)pvStructInfo
;
143 DWORD bytesNeeded
, lenBytes
;
145 switch (link
->dwLinkChoice
)
147 case SPC_FILE_LINK_CHOICE
:
149 DWORD fileNameLen
, fileNameLenBytes
;
152 fileNameLen
= link
->u
.pwszFile
?
153 lstrlenW(link
->u
.pwszFile
) * sizeof(WCHAR
) : 0;
154 CRYPT_EncodeLen(fileNameLen
, NULL
, &fileNameLenBytes
);
155 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, NULL
,
157 bytesNeeded
= 2 + lenBytes
+ fileNameLenBytes
+ fileNameLen
;
160 *pcbEncoded
= bytesNeeded
;
163 else if (*pcbEncoded
< bytesNeeded
)
165 SetLastError(ERROR_MORE_DATA
);
166 *pcbEncoded
= bytesNeeded
;
170 *pcbEncoded
= bytesNeeded
;
171 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2;
172 CRYPT_EncodeLen(1 + fileNameLenBytes
+ fileNameLen
, pbEncoded
,
174 pbEncoded
+= lenBytes
;
175 *pbEncoded
++ = ASN_CONTEXT
;
176 CRYPT_EncodeLen(fileNameLen
, pbEncoded
, &fileNameLenBytes
);
177 pbEncoded
+= fileNameLenBytes
;
178 for (ptr
= link
->u
.pwszFile
; ptr
&& *ptr
; ptr
++)
180 *(WCHAR
*)pbEncoded
= hton16(*ptr
);
181 pbEncoded
+= sizeof(WCHAR
);
187 case SPC_MONIKER_LINK_CHOICE
:
189 DWORD classIdLenBytes
, dataLenBytes
, dataLen
;
190 CRYPT_DATA_BLOB classId
= { sizeof(link
->u
.Moniker
.ClassId
),
191 (BYTE
*)link
->u
.Moniker
.ClassId
};
193 CRYPT_EncodeLen(classId
.cbData
, NULL
, &classIdLenBytes
);
194 CRYPT_EncodeLen(link
->u
.Moniker
.SerializedData
.cbData
, NULL
,
196 dataLen
= 2 + classIdLenBytes
+ classId
.cbData
+
197 dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
198 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
199 bytesNeeded
= 1 + dataLen
+ lenBytes
;
202 *pcbEncoded
= bytesNeeded
;
205 else if (*pcbEncoded
< bytesNeeded
)
207 SetLastError(ERROR_MORE_DATA
);
208 *pcbEncoded
= bytesNeeded
;
214 *pcbEncoded
= bytesNeeded
;
215 *pbEncoded
++ = ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1;
216 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
217 pbEncoded
+= lenBytes
;
218 size
= 1 + classIdLenBytes
+ classId
.cbData
;
219 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
, &classId
,
222 size
= 1 + dataLenBytes
+ link
->u
.Moniker
.SerializedData
.cbData
;
223 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING
, NULL
,
224 &link
->u
.Moniker
.SerializedData
, pbEncoded
, &size
);
230 case SPC_URL_LINK_CHOICE
:
235 /* Check for invalid characters in URL */
238 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
&& ret
; ptr
++)
242 SetLastError(CRYPT_E_INVALID_IA5_STRING
);
249 CRYPT_EncodeLen(urlLen
, NULL
, &lenBytes
);
250 bytesNeeded
= 1 + lenBytes
+ urlLen
;
252 *pcbEncoded
= bytesNeeded
;
253 else if (*pcbEncoded
< bytesNeeded
)
255 SetLastError(ERROR_MORE_DATA
);
256 *pcbEncoded
= bytesNeeded
;
261 *pcbEncoded
= bytesNeeded
;
262 *pbEncoded
++ = ASN_CONTEXT
;
263 CRYPT_EncodeLen(urlLen
, pbEncoded
, &lenBytes
);
264 pbEncoded
+= lenBytes
;
265 for (ptr
= link
->u
.pwszUrl
; ptr
&& *ptr
; ptr
++)
266 *pbEncoded
++ = (BYTE
)*ptr
;
272 SetLastError(E_INVALIDARG
);
277 SetLastError(STATUS_ACCESS_VIOLATION
);
280 TRACE("returning %d\n", ret
);
284 typedef BOOL (WINAPI
*CryptEncodeObjectFunc
)(DWORD
, LPCSTR
, const void *,
287 struct AsnEncodeSequenceItem
289 const void *pvStructInfo
;
290 CryptEncodeObjectFunc encodeFunc
;
291 DWORD size
; /* used during encoding, not for your use */
294 static BOOL WINAPI
CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType
,
295 struct AsnEncodeSequenceItem items
[], DWORD cItem
, BYTE
*pbEncoded
,
299 DWORD i
, dataLen
= 0;
301 TRACE("%p, %d, %p, %d\n", items
, cItem
, pbEncoded
, *pcbEncoded
);
302 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
304 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
305 items
[i
].pvStructInfo
, NULL
, &items
[i
].size
);
306 /* Some functions propagate their errors through the size */
308 *pcbEncoded
= items
[i
].size
;
309 dataLen
+= items
[i
].size
;
313 DWORD lenBytes
, bytesNeeded
;
315 CRYPT_EncodeLen(dataLen
, NULL
, &lenBytes
);
316 bytesNeeded
= 1 + lenBytes
+ dataLen
;
318 *pcbEncoded
= bytesNeeded
;
319 else if (*pcbEncoded
< bytesNeeded
)
321 *pcbEncoded
= bytesNeeded
;
322 SetLastError(ERROR_MORE_DATA
);
327 *pcbEncoded
= bytesNeeded
;
328 *pbEncoded
++ = ASN_SEQUENCE
;
329 CRYPT_EncodeLen(dataLen
, pbEncoded
, &lenBytes
);
330 pbEncoded
+= lenBytes
;
331 for (i
= 0; ret
&& i
< cItem
; i
++)
333 ret
= items
[i
].encodeFunc(dwCertEncodingType
, NULL
,
334 items
[i
].pvStructInfo
, pbEncoded
, &items
[i
].size
);
335 /* Some functions propagate their errors through the size */
337 *pcbEncoded
= items
[i
].size
;
338 pbEncoded
+= items
[i
].size
;
342 TRACE("returning %d\n", ret
);
346 static BOOL WINAPI
CRYPT_AsnEncodeBits(DWORD dwCertEncodingType
,
347 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
354 const CRYPT_BIT_BLOB
*blob
= (const CRYPT_BIT_BLOB
*)pvStructInfo
;
355 DWORD bytesNeeded
, lenBytes
, dataBytes
;
358 /* yep, MS allows cUnusedBits to be >= 8 */
359 if (!blob
->cUnusedBits
)
361 dataBytes
= blob
->cbData
;
364 else if (blob
->cbData
* 8 > blob
->cUnusedBits
)
366 dataBytes
= (blob
->cbData
* 8 - blob
->cUnusedBits
) / 8 + 1;
367 unusedBits
= blob
->cUnusedBits
>= 8 ? blob
->cUnusedBits
/ 8 :
375 CRYPT_EncodeLen(dataBytes
+ 1, NULL
, &lenBytes
);
376 bytesNeeded
= 1 + lenBytes
+ dataBytes
+ 1;
379 *pcbEncoded
= bytesNeeded
;
382 else if (*pcbEncoded
< bytesNeeded
)
384 *pcbEncoded
= bytesNeeded
;
385 SetLastError(ERROR_MORE_DATA
);
390 *pcbEncoded
= bytesNeeded
;
391 *pbEncoded
++ = ASN_BITSTRING
;
392 CRYPT_EncodeLen(dataBytes
+ 1, pbEncoded
, &lenBytes
);
393 pbEncoded
+= lenBytes
;
394 *pbEncoded
++ = unusedBits
;
397 BYTE mask
= 0xff << unusedBits
;
401 memcpy(pbEncoded
, blob
->pbData
, dataBytes
- 1);
402 pbEncoded
+= dataBytes
- 1;
404 *pbEncoded
= *(blob
->pbData
+ dataBytes
- 1) & mask
;
410 SetLastError(STATUS_ACCESS_VIOLATION
);
416 struct AsnConstructedItem
419 const void *pvStructInfo
;
420 CryptEncodeObjectFunc encodeFunc
;
423 static BOOL WINAPI
CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType
,
424 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
428 const struct AsnConstructedItem
*item
=
429 (const struct AsnConstructedItem
*)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
=
476 (const SPC_PE_IMAGE_DATA
*)pvStructInfo
;
479 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
480 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
,
485 struct AsnEncodeSequenceItem items
[2] = {
488 struct AsnConstructedItem constructed
= { 0, imageData
->pFile
,
489 WVTAsn1SpcLinkEncode
};
492 if (imageData
->Flags
.cbData
)
494 items
[cItem
].pvStructInfo
= &imageData
->Flags
;
495 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeBits
;
498 if (imageData
->pFile
)
500 items
[cItem
].pvStructInfo
= &constructed
;
501 items
[cItem
].encodeFunc
= CRYPT_AsnEncodeConstructed
;
505 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
, cItem
,
506 pbEncoded
, pcbEncoded
);
510 SetLastError(STATUS_ACCESS_VIOLATION
);
513 TRACE("returning %d\n", ret
);
517 static BOOL WINAPI
CRYPT_AsnEncodeOid(DWORD dwCertEncodingType
,
518 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
521 LPCSTR pszObjId
= (LPCSTR
)pvStructInfo
;
522 DWORD bytesNeeded
= 0, lenBytes
;
527 TRACE("%s\n", debugstr_a(pszObjId
));
534 if (sscanf(pszObjId
, "%d.%d.%n", &val1
, &val2
, &firstPos
) != 2)
536 SetLastError(CRYPT_E_ASN1_ERROR
);
540 firstByte
= val1
* 40 + val2
;
541 ptr
= pszObjId
+ firstPos
;
546 /* note I assume each component is at most 32-bits long in base 2 */
547 if (sscanf(ptr
, "%d%n", &val1
, &pos
) == 1)
549 if (val1
>= 0x10000000)
551 else if (val1
>= 0x200000)
553 else if (val1
>= 0x4000)
555 else if (val1
>= 0x80)
565 SetLastError(CRYPT_E_ASN1_ERROR
);
569 CRYPT_EncodeLen(bytesNeeded
, NULL
, &lenBytes
);
573 bytesNeeded
+= 1 + lenBytes
;
576 if (*pcbEncoded
< bytesNeeded
)
578 SetLastError(ERROR_MORE_DATA
);
583 *pbEncoded
++ = ASN_OBJECTIDENTIFIER
;
584 CRYPT_EncodeLen(bytesNeeded
- 1 - lenBytes
, pbEncoded
, &lenBytes
);
585 pbEncoded
+= lenBytes
;
591 *pbEncoded
++ = firstByte
;
592 ptr
= pszObjId
+ firstPos
;
595 sscanf(ptr
, "%d%n", &val
, &pos
);
597 unsigned char outBytes
[5];
600 if (val
>= 0x10000000)
602 else if (val
>= 0x200000)
604 else if (val
>= 0x4000)
606 else if (val
>= 0x80)
610 for (i
= numBytes
; i
> 0; i
--)
612 outBytes
[i
- 1] = val
& 0x7f;
615 for (i
= 0; i
< numBytes
- 1; i
++)
616 *pbEncoded
++ = outBytes
[i
] | 0x80;
617 *pbEncoded
++ = outBytes
[i
];
626 *pcbEncoded
= bytesNeeded
;
630 static BOOL WINAPI
CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType
,
631 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
634 const CRYPT_DER_BLOB
*blob
= (const CRYPT_DER_BLOB
*)pvStructInfo
;
638 *pcbEncoded
= blob
->cbData
;
639 else if (*pcbEncoded
< blob
->cbData
)
641 *pcbEncoded
= blob
->cbData
;
642 SetLastError(ERROR_MORE_DATA
);
648 memcpy(pbEncoded
, blob
->pbData
, blob
->cbData
);
649 *pcbEncoded
= blob
->cbData
;
654 static BOOL WINAPI
CRYPT_AsnEncodeAlgorithmIdWithNullParams(
655 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const void *pvStructInfo
,
656 BYTE
*pbEncoded
, DWORD
*pcbEncoded
)
658 const CRYPT_ALGORITHM_IDENTIFIER
*algo
=
659 (const CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
660 static const BYTE asn1Null
[] = { ASN_NULL
, 0 };
661 static const CRYPT_DATA_BLOB nullBlob
= { sizeof(asn1Null
),
664 struct AsnEncodeSequenceItem items
[2] = {
665 { algo
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
666 { NULL
, CRYPT_CopyEncodedBlob
, 0 },
669 if (algo
->Parameters
.cbData
)
670 items
[1].pvStructInfo
= &algo
->Parameters
;
672 items
[1].pvStructInfo
= &nullBlob
;
673 ret
= CRYPT_AsnEncodeSequence(dwCertEncodingType
, items
,
674 sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
678 static BOOL WINAPI
CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType
,
679 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
682 const CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
=
683 (const CRYPT_ATTRIBUTE_TYPE_VALUE
*)pvStructInfo
;
684 struct AsnEncodeSequenceItem items
[] = {
685 { &typeValue
->pszObjId
, CRYPT_AsnEncodeOid
, 0 },
686 { &typeValue
->Value
, CRYPT_CopyEncodedBlob
, 0 },
689 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
690 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
695 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm
;
696 CRYPT_HASH_BLOB Digest
;
699 static BOOL WINAPI
CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType
,
700 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
703 const struct SPCDigest
*digest
= (const struct SPCDigest
*)pvStructInfo
;
704 struct AsnEncodeSequenceItem items
[] = {
705 { &digest
->DigestAlgorithm
, CRYPT_AsnEncodeAlgorithmIdWithNullParams
, 0 },
706 { &digest
->Digest
, CRYPT_CopyEncodedBlob
, 0 },
709 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
710 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
713 BOOL WINAPI
WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType
,
714 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
719 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
720 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
724 const SPC_INDIRECT_DATA_CONTENT
*data
=
725 (const SPC_INDIRECT_DATA_CONTENT
*)pvStructInfo
;
726 struct AsnEncodeSequenceItem items
[] = {
727 { &data
->Data
, CRYPT_AsnEncodeAttributeTypeValue
, 0 },
728 { &data
->DigestAlgorithm
, CRYPT_AsnEncodeSPCDigest
, 0 },
731 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
732 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
736 SetLastError(STATUS_ACCESS_VIOLATION
);
742 static BOOL WINAPI
CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType
,
743 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
747 LPCWSTR str
= (LPCWSTR
)pvStructInfo
;
748 DWORD bytesNeeded
, lenBytes
, strLen
;
751 strLen
= lstrlenW(str
);
754 CRYPT_EncodeLen(strLen
* 2, NULL
, &lenBytes
);
755 bytesNeeded
= 1 + lenBytes
+ strLen
* 2;
757 *pcbEncoded
= bytesNeeded
;
758 else if (*pcbEncoded
< bytesNeeded
)
760 *pcbEncoded
= bytesNeeded
;
761 SetLastError(ERROR_MORE_DATA
);
768 *pcbEncoded
= bytesNeeded
;
769 *pbEncoded
++ = ASN_BMPSTRING
;
770 CRYPT_EncodeLen(strLen
* 2, pbEncoded
, &lenBytes
);
771 pbEncoded
+= lenBytes
;
772 for (i
= 0; i
< strLen
; i
++)
774 *pbEncoded
++ = (str
[i
] & 0xff00) >> 8;
775 *pbEncoded
++ = str
[i
] & 0x00ff;
781 static BOOL WINAPI
CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType
,
782 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
789 DWORD significantBytes
, lenBytes
, bytesNeeded
;
792 const CRYPT_INTEGER_BLOB
*blob
=
793 (const CRYPT_INTEGER_BLOB
*)pvStructInfo
;
795 significantBytes
= blob
->cbData
;
796 if (significantBytes
)
798 if (blob
->pbData
[significantBytes
- 1] & 0x80)
800 /* negative, lop off leading (little-endian) 0xffs */
801 for (; significantBytes
> 0 &&
802 blob
->pbData
[significantBytes
- 1] == 0xff; significantBytes
--)
804 if (blob
->pbData
[significantBytes
- 1] < 0x80)
812 /* positive, lop off leading (little-endian) zeroes */
813 for (; significantBytes
> 0 &&
814 !blob
->pbData
[significantBytes
- 1]; significantBytes
--)
816 if (significantBytes
== 0)
817 significantBytes
= 1;
818 if (blob
->pbData
[significantBytes
- 1] > 0x7f)
826 CRYPT_EncodeLen(significantBytes
+ 1, NULL
, &lenBytes
);
828 CRYPT_EncodeLen(significantBytes
, NULL
, &lenBytes
);
829 bytesNeeded
= 1 + lenBytes
+ significantBytes
;
834 *pcbEncoded
= bytesNeeded
;
837 else if (*pcbEncoded
< bytesNeeded
)
839 *pcbEncoded
= bytesNeeded
;
840 SetLastError(ERROR_MORE_DATA
);
845 *pcbEncoded
= bytesNeeded
;
846 *pbEncoded
++ = ASN_INTEGER
;
849 CRYPT_EncodeLen(significantBytes
+ 1, pbEncoded
, &lenBytes
);
850 pbEncoded
+= lenBytes
;
851 *pbEncoded
++ = padByte
;
855 CRYPT_EncodeLen(significantBytes
, pbEncoded
, &lenBytes
);
856 pbEncoded
+= lenBytes
;
858 for (; significantBytes
> 0; significantBytes
--)
859 *(pbEncoded
++) = blob
->pbData
[significantBytes
- 1];
865 SetLastError(STATUS_ACCESS_VIOLATION
);
872 BOOL WINAPI
CRYPT_AsnEncodeInt(DWORD dwCertEncodingType
,
873 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
876 CRYPT_INTEGER_BLOB blob
= { sizeof(INT
), (BYTE
*)pvStructInfo
};
878 return CRYPT_AsnEncodeInteger(dwCertEncodingType
, X509_MULTI_BYTE_INTEGER
,
879 &blob
, pbEncoded
, pcbEncoded
);
882 BOOL WINAPI
WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType
,
883 LPCSTR lpszStructType
, const void *pvStructInfo
, BYTE
*pbEncoded
,
888 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType
,
889 debugstr_a(lpszStructType
), pvStructInfo
, pbEncoded
, pcbEncoded
);
893 const CAT_MEMBERINFO
*info
= (const CAT_MEMBERINFO
*)pvStructInfo
;
894 struct AsnEncodeSequenceItem items
[] = {
895 { info
->pwszSubjGuid
, CRYPT_AsnEncodeBMPString
, 0 },
896 { &info
->dwCertVersion
, CRYPT_AsnEncodeInt
, 0 },
899 ret
= CRYPT_AsnEncodeSequence(X509_ASN_ENCODING
,
900 items
, sizeof(items
) / sizeof(items
[0]), pbEncoded
, pcbEncoded
);
904 SetLastError(STATUS_ACCESS_VIOLATION
);
910 /* Gets the number of length bytes from the given (leading) length byte */
911 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
913 /* Helper function to get the encoded length of the data starting at pbEncoded,
914 * where pbEncoded[0] is the tag. If the data are too short to contain a
915 * length or if the length is too large for cbEncoded, sets an appropriate
916 * error code and returns FALSE.
918 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
924 SetLastError(CRYPT_E_ASN1_CORRUPT
);
927 else if (pbEncoded
[1] <= 0x7f)
929 if (pbEncoded
[1] + 1 > cbEncoded
)
931 SetLastError(CRYPT_E_ASN1_EOD
);
940 else if (pbEncoded
[1] == 0x80)
942 FIXME("unimplemented for indefinite-length encoding\n");
943 SetLastError(CRYPT_E_ASN1_CORRUPT
);
948 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
950 if (lenLen
> sizeof(DWORD
) + 1)
952 SetLastError(CRYPT_E_ASN1_LARGE
);
955 else if (lenLen
+ 2 > cbEncoded
)
957 SetLastError(CRYPT_E_ASN1_CORRUPT
);
970 if (out
+ lenLen
+ 1 > cbEncoded
)
972 SetLastError(CRYPT_E_ASN1_EOD
);
985 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
986 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
987 void *pvStructInfo
, DWORD
*pcbStructInfo
)
990 DWORD bytesNeeded
, dataLen
;
992 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
993 pvStructInfo
, *pcbStructInfo
);
997 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1000 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
1002 SetLastError(CRYPT_E_ASN1_BADTAG
);
1005 else if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1007 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1008 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
1010 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
1012 *pcbStructInfo
= bytesNeeded
;
1013 else if (*pcbStructInfo
< bytesNeeded
)
1015 SetLastError(ERROR_MORE_DATA
);
1016 *pcbStructInfo
= bytesNeeded
;
1021 CRYPT_DATA_BLOB
*blob
;
1022 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1024 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
1025 blob
->cbData
= dataLen
;
1026 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1027 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
1030 assert(blob
->pbData
);
1032 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
1040 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType
,
1041 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1042 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1045 DWORD bytesNeeded
= sizeof(SPC_LINK
), dataLen
;
1047 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1048 pvStructInfo
, *pcbStructInfo
);
1050 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1052 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1055 switch (pbEncoded
[0])
1058 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
1060 *pcbStructInfo
= bytesNeeded
;
1061 else if (*pcbStructInfo
< bytesNeeded
)
1063 *pcbStructInfo
= bytesNeeded
;
1064 SetLastError(ERROR_MORE_DATA
);
1069 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1072 link
->dwLinkChoice
= SPC_URL_LINK_CHOICE
;
1073 for (i
= 0; i
< dataLen
; i
++)
1074 link
->u
.pwszUrl
[i
] =
1075 *(pbEncoded
+ 1 + lenBytes
+ i
);
1076 link
->u
.pwszUrl
[i
] = '\0';
1077 TRACE("returning url %s\n", debugstr_w(link
->u
.pwszUrl
));
1080 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1:
1082 CRYPT_DATA_BLOB classId
;
1083 DWORD size
= sizeof(classId
);
1085 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1086 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
1087 CRYPT_DECODE_NOCOPY_FLAG
, &classId
, &size
)))
1089 if (classId
.cbData
!= sizeof(SPC_UUID
))
1091 SetLastError(CRYPT_E_BAD_ENCODE
);
1096 CRYPT_DATA_BLOB data
;
1098 /* The tag length for the classId must be 1 since the
1099 * length is correct.
1101 size
= sizeof(data
);
1102 if ((ret
= CRYPT_AsnDecodeOctets(dwCertEncodingType
, NULL
,
1103 pbEncoded
+ 3 + lenBytes
+ classId
.cbData
,
1104 cbEncoded
- 3 - lenBytes
- classId
.cbData
,
1105 CRYPT_DECODE_NOCOPY_FLAG
, &data
, &size
)))
1107 bytesNeeded
+= data
.cbData
;
1109 *pcbStructInfo
= bytesNeeded
;
1110 else if (*pcbStructInfo
< bytesNeeded
)
1112 *pcbStructInfo
= bytesNeeded
;
1113 SetLastError(ERROR_MORE_DATA
);
1118 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1120 link
->dwLinkChoice
= SPC_MONIKER_LINK_CHOICE
;
1121 /* pwszFile pointer was set by caller, copy it
1122 * before overwriting it
1124 link
->u
.Moniker
.SerializedData
.pbData
=
1125 (BYTE
*)link
->u
.pwszFile
;
1126 memcpy(link
->u
.Moniker
.ClassId
, classId
.pbData
,
1128 memcpy(link
->u
.Moniker
.SerializedData
.pbData
,
1129 data
.pbData
, data
.cbData
);
1130 link
->u
.Moniker
.SerializedData
.cbData
= data
.cbData
;
1137 case ASN_CONSTRUCTOR
| ASN_CONTEXT
| 2:
1138 if (dataLen
&& pbEncoded
[1 + lenBytes
] != ASN_CONTEXT
)
1139 SetLastError(CRYPT_E_ASN1_BADTAG
);
1140 else if ((ret
= CRYPT_GetLen(pbEncoded
+ 1 + lenBytes
, dataLen
,
1143 BYTE realLenBytes
= GET_LEN_BYTES(pbEncoded
[2 + lenBytes
]);
1145 bytesNeeded
+= realDataLen
+ sizeof(WCHAR
);
1147 *pcbStructInfo
= bytesNeeded
;
1148 else if (*pcbStructInfo
< bytesNeeded
)
1150 *pcbStructInfo
= bytesNeeded
;
1151 SetLastError(ERROR_MORE_DATA
);
1156 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1158 const BYTE
*ptr
= pbEncoded
+ 2 + lenBytes
+ realLenBytes
;
1160 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1161 for (i
= 0; i
< dataLen
/ sizeof(WCHAR
); i
++)
1162 link
->u
.pwszFile
[i
] =
1163 hton16(*(WORD
*)(ptr
+ i
* sizeof(WCHAR
)));
1164 link
->u
.pwszFile
[realDataLen
/ sizeof(WCHAR
)] = '\0';
1165 TRACE("returning file %s\n", debugstr_w(link
->u
.pwszFile
));
1170 bytesNeeded
+= sizeof(WCHAR
);
1172 *pcbStructInfo
= bytesNeeded
;
1173 else if (*pcbStructInfo
< bytesNeeded
)
1175 *pcbStructInfo
= bytesNeeded
;
1176 SetLastError(ERROR_MORE_DATA
);
1181 PSPC_LINK link
= (PSPC_LINK
)pvStructInfo
;
1183 link
->dwLinkChoice
= SPC_FILE_LINK_CHOICE
;
1184 link
->u
.pwszFile
[0] = '\0';
1190 SetLastError(CRYPT_E_ASN1_BADTAG
);
1193 TRACE("returning %d\n", ret
);
1197 BOOL WINAPI
WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType
,
1198 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1199 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1203 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1204 pvStructInfo
, *pcbStructInfo
);
1210 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1211 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, NULL
, &bytesNeeded
);
1215 *pcbStructInfo
= bytesNeeded
;
1216 else if (*pcbStructInfo
< bytesNeeded
)
1218 *pcbStructInfo
= bytesNeeded
;
1219 SetLastError(ERROR_MORE_DATA
);
1224 SPC_LINK
*link
= (SPC_LINK
*)pvStructInfo
;
1227 (LPWSTR
)((BYTE
*)pvStructInfo
+ sizeof(SPC_LINK
));
1228 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1229 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
1236 SetLastError(STATUS_ACCESS_VIOLATION
);
1239 TRACE("returning %d\n", ret
);
1243 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
1244 DWORD
, DWORD
, void *, DWORD
*);
1247 * The expected tag of the item. If tag is 0, decodeFunc is called
1248 * regardless of the tag value seen.
1250 * A sequence is decoded into a struct. The offset member is the
1251 * offset of this item within that struct.
1253 * The decoder function to use. If this is NULL, then the member isn't
1254 * decoded, but minSize space is reserved for it.
1256 * The minimum amount of space occupied after decoding. You must set this.
1258 * If true, and the tag doesn't match the expected tag for this item,
1259 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1260 * filled with 0 for this member.
1261 * hasPointer, pointerOffset:
1262 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1263 * the offset within the struct of the data pointer (or to the
1264 * first data pointer, if more than one exist).
1266 * Used by CRYPT_AsnDecodeSequence, not for your use.
1268 struct AsnDecodeSequenceItem
1272 CryptDecodeObjectFunc decodeFunc
;
1276 DWORD pointerOffset
;
1280 /* Decodes the items in a sequence, where the items are described in items,
1281 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1282 * pvStructInfo. nextData is a pointer to the memory location at which the
1283 * first decoded item with a dynamic pointer should point.
1284 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1286 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
1287 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1288 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
1292 DWORD i
, decoded
= 0;
1293 const BYTE
*ptr
= pbEncoded
;
1295 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
1296 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
1298 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
1300 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
1304 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
1307 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
1309 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
1311 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
1313 TRACE("Setting next pointer to %p\n",
1315 *(BYTE
**)((BYTE
*)pvStructInfo
+
1316 items
[i
].pointerOffset
) = nextData
;
1318 if (items
[i
].decodeFunc
)
1321 TRACE("decoding item %d\n", i
);
1323 TRACE("sizing item %d\n", i
);
1324 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
1325 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
1326 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
1327 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
1328 : NULL
, &items
[i
].size
);
1331 /* Account for alignment padding */
1332 if (items
[i
].size
% sizeof(DWORD
))
1333 items
[i
].size
+= sizeof(DWORD
) -
1334 items
[i
].size
% sizeof(DWORD
);
1335 TRACE("item %d size: %d\n", i
, items
[i
].size
);
1336 if (nextData
&& items
[i
].hasPointer
&&
1337 items
[i
].size
> items
[i
].minSize
)
1338 nextData
+= items
[i
].size
- items
[i
].minSize
;
1339 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1340 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1341 TRACE("item %d: decoded %d bytes\n", i
,
1342 1 + nextItemLenBytes
+ nextItemLen
);
1344 else if (items
[i
].optional
&&
1345 GetLastError() == CRYPT_E_ASN1_BADTAG
)
1347 TRACE("skipping optional item %d\n", i
);
1348 items
[i
].size
= items
[i
].minSize
;
1349 SetLastError(NOERROR
);
1353 TRACE("item %d failed: %08x\n", i
,
1358 TRACE("item %d: decoded %d bytes\n", i
,
1359 1 + nextItemLenBytes
+ nextItemLen
);
1360 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
1361 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
1362 items
[i
].size
= items
[i
].minSize
;
1365 else if (items
[i
].optional
)
1367 TRACE("skipping optional item %d\n", i
);
1368 items
[i
].size
= items
[i
].minSize
;
1372 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1373 i
, ptr
[0], items
[i
].tag
);
1374 SetLastError(CRYPT_E_ASN1_BADTAG
);
1379 else if (items
[i
].optional
)
1381 TRACE("missing optional item %d, skipping\n", i
);
1382 items
[i
].size
= items
[i
].minSize
;
1386 TRACE("not enough bytes for item %d, failing\n", i
);
1387 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1392 *cbDecoded
= decoded
;
1393 TRACE("returning %d\n", ret
);
1397 /* This decodes an arbitrary sequence into a contiguous block of memory
1398 * (basically, a struct.) Each element being decoded is described by a struct
1399 * AsnDecodeSequenceItem, see above.
1400 * startingPointer is an optional pointer to the first place where dynamic
1401 * data will be stored. If you know the starting offset, you may pass it
1402 * here. Otherwise, pass NULL, and one will be inferred from the items.
1404 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
1405 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
1406 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1407 void *startingPointer
)
1411 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items
, cItem
, pbEncoded
,
1412 cbEncoded
, dwFlags
, pvStructInfo
, *pcbStructInfo
, startingPointer
);
1414 if (pbEncoded
[0] == ASN_SEQUENCE
)
1418 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1420 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
1421 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
1423 cbEncoded
-= 1 + lenBytes
;
1424 if (cbEncoded
< dataLen
)
1426 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
1428 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1432 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
1433 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
1434 if (ret
&& cbDecoded
!= dataLen
)
1436 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
1438 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1443 DWORD i
, bytesNeeded
= 0, structSize
= 0;
1445 for (i
= 0; i
< cItem
; i
++)
1447 bytesNeeded
+= items
[i
].size
;
1448 structSize
+= items
[i
].minSize
;
1451 *pcbStructInfo
= bytesNeeded
;
1452 else if (*pcbStructInfo
< bytesNeeded
)
1454 SetLastError(ERROR_MORE_DATA
);
1455 *pcbStructInfo
= bytesNeeded
;
1462 *pcbStructInfo
= bytesNeeded
;
1463 if (startingPointer
)
1464 nextData
= (BYTE
*)startingPointer
;
1466 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
1467 memset(pvStructInfo
, 0, structSize
);
1468 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
1469 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
1477 SetLastError(CRYPT_E_ASN1_BADTAG
);
1480 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1484 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
1485 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1486 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1490 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
1491 pvStructInfo
, *pcbStructInfo
);
1493 if (pbEncoded
[0] == ASN_BITSTRING
)
1495 DWORD bytesNeeded
, dataLen
;
1497 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1499 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1500 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
1502 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
1504 *pcbStructInfo
= bytesNeeded
;
1505 else if (*pcbStructInfo
< bytesNeeded
)
1507 *pcbStructInfo
= bytesNeeded
;
1508 SetLastError(ERROR_MORE_DATA
);
1513 CRYPT_BIT_BLOB
*blob
;
1515 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
1516 blob
->cbData
= dataLen
- 1;
1517 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
1518 GET_LEN_BYTES(pbEncoded
[1]));
1519 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1521 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
1522 GET_LEN_BYTES(pbEncoded
[1]);
1526 assert(blob
->pbData
);
1529 BYTE mask
= 0xff << blob
->cUnusedBits
;
1531 memcpy(blob
->pbData
, pbEncoded
+ 2 +
1532 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
1533 blob
->pbData
[blob
->cbData
- 1] &= mask
;
1541 SetLastError(CRYPT_E_ASN1_BADTAG
);
1544 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1548 static BOOL WINAPI
CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType
,
1549 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1550 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1555 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1557 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1559 SPC_LINK
**pLink
= (SPC_LINK
**)pvStructInfo
;
1561 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
, lpszStructType
,
1562 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, NULL
, &size
);
1566 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1567 else if (*pcbStructInfo
< size
+ sizeof(PSPC_LINK
))
1569 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1570 SetLastError(ERROR_MORE_DATA
);
1575 *pcbStructInfo
= size
+ sizeof(PSPC_LINK
);
1576 /* Set imageData's pointer if necessary */
1577 if (size
> sizeof(SPC_LINK
))
1579 (*pLink
)->u
.pwszUrl
=
1580 (LPWSTR
)((BYTE
*)*pLink
+ sizeof(SPC_LINK
));
1582 ret
= CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType
,
1583 lpszStructType
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
1584 *pLink
, pcbStructInfo
);
1591 BOOL WINAPI
WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType
,
1592 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1593 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1597 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1598 pvStructInfo
, *pcbStructInfo
);
1602 struct AsnDecodeSequenceItem items
[] = {
1603 { ASN_BITSTRING
, offsetof(SPC_PE_IMAGE_DATA
, Flags
),
1604 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
1605 offsetof(SPC_PE_IMAGE_DATA
, Flags
.pbData
), 0 },
1606 { ASN_CONSTRUCTOR
| ASN_CONTEXT
, offsetof(SPC_PE_IMAGE_DATA
, pFile
),
1607 CRYPT_AsnDecodeSPCLinkPointer
, sizeof(PSPC_LINK
), TRUE
, TRUE
,
1608 offsetof(SPC_PE_IMAGE_DATA
, pFile
), 0 },
1611 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1612 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1613 pvStructInfo
, pcbStructInfo
, NULL
);
1617 SetLastError(STATUS_ACCESS_VIOLATION
);
1620 TRACE("returning %d\n", ret
);
1624 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1625 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1626 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1631 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1632 pvStructInfo
, *pcbStructInfo
);
1634 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1636 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1637 DWORD bytesNeeded
= sizeof(LPSTR
);
1641 /* The largest possible string for the first two components
1642 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1647 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1648 pbEncoded
[1 + lenBytes
] / 40,
1649 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1651 bytesNeeded
+= strlen(firstTwo
) + 1;
1652 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1653 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1655 /* large enough for ".4000000" */
1659 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1666 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1669 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1676 snprintf(str
, sizeof(str
), ".%d", val
);
1677 bytesNeeded
+= strlen(str
);
1682 *pcbStructInfo
= bytesNeeded
;
1683 else if (*pcbStructInfo
< bytesNeeded
)
1685 *pcbStructInfo
= bytesNeeded
;
1686 SetLastError(ERROR_MORE_DATA
);
1694 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1697 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1698 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1700 pszObjId
+= strlen(pszObjId
);
1701 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1702 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1706 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1715 sprintf(pszObjId
, ".%d", val
);
1716 pszObjId
+= strlen(pszObjId
);
1720 *(LPSTR
*)pvStructInfo
= NULL
;
1721 *pcbStructInfo
= bytesNeeded
;
1727 static BOOL WINAPI
CRYPT_AsnDecodeOid(DWORD dwCertEncodingType
,
1728 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1729 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1733 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1734 pvStructInfo
, *pcbStructInfo
);
1737 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1738 else if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1739 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1740 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
1742 SetLastError(CRYPT_E_ASN1_BADTAG
);
1746 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1747 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1748 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1751 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1753 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1754 pvStructInfo
, *pcbStructInfo
);
1756 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1757 bytesNeeded
+= cbEncoded
;
1759 *pcbStructInfo
= bytesNeeded
;
1760 else if (*pcbStructInfo
< bytesNeeded
)
1762 SetLastError(ERROR_MORE_DATA
);
1763 *pcbStructInfo
= bytesNeeded
;
1768 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
1770 *pcbStructInfo
= bytesNeeded
;
1771 blob
->cbData
= cbEncoded
;
1772 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1773 blob
->pbData
= (LPBYTE
)pbEncoded
;
1776 assert(blob
->pbData
);
1777 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1783 static BOOL WINAPI
CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType
,
1784 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1785 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1787 CRYPT_ATTRIBUTE_TYPE_VALUE
*typeValue
=
1788 (CRYPT_ATTRIBUTE_TYPE_VALUE
*)pvStructInfo
;
1789 struct AsnDecodeSequenceItem items
[] = {
1790 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
),
1791 CRYPT_AsnDecodeOid
, sizeof(LPSTR
), FALSE
, TRUE
,
1792 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, pszObjId
), 0 },
1793 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
),
1794 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_DATA_BLOB
), TRUE
, TRUE
,
1795 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE
, Value
.pbData
), 0 },
1798 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1799 pvStructInfo
, *pcbStructInfo
);
1801 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1802 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1803 pvStructInfo
, pcbStructInfo
,
1804 typeValue
? typeValue
->pszObjId
: NULL
);
1807 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
1808 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1809 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1811 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
1812 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
1814 struct AsnDecodeSequenceItem items
[] = {
1815 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
1816 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1817 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
1818 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
1819 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
1820 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
1823 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1824 pvStructInfo
, *pcbStructInfo
);
1826 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1827 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1828 pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
1829 if (ret
&& pvStructInfo
)
1831 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
1832 debugstr_a(algo
->pszObjId
));
1837 static BOOL WINAPI
CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType
,
1838 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1839 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1841 struct SPCDigest
*digest
=
1842 (struct SPCDigest
*)pvStructInfo
;
1843 struct AsnDecodeSequenceItem items
[] = {
1844 { ASN_SEQUENCEOF
, offsetof(struct SPCDigest
, DigestAlgorithm
),
1845 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
1847 offsetof(struct SPCDigest
, DigestAlgorithm
.pszObjId
), 0 },
1848 { ASN_OCTETSTRING
, offsetof(struct SPCDigest
, Digest
),
1849 CRYPT_AsnDecodeOctets
, sizeof(CRYPT_DER_BLOB
),
1850 FALSE
, TRUE
, offsetof(struct SPCDigest
, Digest
.pbData
), 0 },
1853 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1854 pvStructInfo
, *pcbStructInfo
);
1856 return CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1857 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1858 pvStructInfo
, pcbStructInfo
,
1859 digest
? digest
->DigestAlgorithm
.pszObjId
: NULL
);
1862 BOOL WINAPI
WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType
,
1863 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1864 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1868 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1869 pvStructInfo
, *pcbStructInfo
);
1873 struct AsnDecodeSequenceItem items
[] = {
1874 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
),
1875 CRYPT_AsnDecodeAttributeTypeValue
,
1876 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE
), FALSE
, TRUE
,
1877 offsetof(SPC_INDIRECT_DATA_CONTENT
, Data
.pszObjId
), 0 },
1878 { ASN_SEQUENCEOF
, offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
),
1879 CRYPT_AsnDecodeSPCDigest
, sizeof(struct SPCDigest
),
1881 offsetof(SPC_INDIRECT_DATA_CONTENT
, DigestAlgorithm
.pszObjId
), 0 },
1884 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1885 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1886 pvStructInfo
, pcbStructInfo
, NULL
);
1890 SetLastError(STATUS_ACCESS_VIOLATION
);
1893 TRACE("returning %d\n", ret
);
1897 BOOL WINAPI
WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType
,
1898 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1899 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1901 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1902 pvStructInfo
, *pcbStructInfo
);
1906 BOOL WINAPI
WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType
,
1907 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1908 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1910 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1911 pvStructInfo
, *pcbStructInfo
);