wintrust: Implement WVTAsn1SpcSpOpusInfoEncode.
[wine/wine64.git] / dlls / wintrust / asn.c
blob3a51c91e0cceac4efd435c96b9271e12117d4886
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 "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <assert.h>
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "wincrypt.h"
32 #include "wintrust.h"
33 #include "snmp.h"
34 #include "winternl.h"
35 #include "wine/debug.h"
36 #include "wine/exception.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
40 #ifdef WORDS_BIGENDIAN
42 #define hton16(x) (x)
43 #define n16toh(x) (x)
45 #else
47 #define hton16(x) RtlUshortByteSwap(x)
48 #define n16toh(x) RtlUshortByteSwap(x)
50 #endif
52 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
53 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
54 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
56 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
58 DWORD bytesNeeded, significantBytes = 0;
60 if (len <= 0x7f)
61 bytesNeeded = 1;
62 else
64 DWORD temp;
66 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
67 temp <<= 8, significantBytes--)
69 bytesNeeded = significantBytes + 1;
71 if (!pbEncoded)
73 *pcbEncoded = bytesNeeded;
74 return TRUE;
76 if (*pcbEncoded < bytesNeeded)
78 SetLastError(ERROR_MORE_DATA);
79 return FALSE;
81 if (len <= 0x7f)
82 *pbEncoded = (BYTE)len;
83 else
85 DWORD i;
87 *pbEncoded++ = significantBytes | 0x80;
88 for (i = 0; i < significantBytes; i++)
90 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
91 len >>= 8;
94 *pcbEncoded = bytesNeeded;
95 return TRUE;
98 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
100 DWORD *pcbEncoded)
102 BOOL ret = TRUE;
103 const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
104 DWORD bytesNeeded, lenBytes;
106 TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
107 *pcbEncoded);
109 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
110 bytesNeeded = 1 + lenBytes + blob->cbData;
111 if (!pbEncoded)
112 *pcbEncoded = bytesNeeded;
113 else if (*pcbEncoded < bytesNeeded)
115 *pcbEncoded = bytesNeeded;
116 SetLastError(ERROR_MORE_DATA);
117 ret = FALSE;
119 else
121 *pbEncoded++ = ASN_OCTETSTRING;
122 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
123 pbEncoded += lenBytes;
124 if (blob->cbData)
125 memcpy(pbEncoded, blob->pbData, blob->cbData);
127 TRACE("returning %d\n", ret);
128 return ret;
131 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
132 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
133 DWORD *pcbEncoded)
135 BOOL ret = FALSE;
137 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
138 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
139 pcbEncoded);
141 __TRY
143 const SPC_LINK *link = (const SPC_LINK *)pvStructInfo;
144 DWORD bytesNeeded, lenBytes;
146 switch (link->dwLinkChoice)
148 case SPC_FILE_LINK_CHOICE:
150 DWORD fileNameLen, fileNameLenBytes;
151 LPWSTR ptr;
153 fileNameLen = link->u.pwszFile ?
154 lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
155 CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
156 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
157 &lenBytes);
158 bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
159 if (!pbEncoded)
161 *pcbEncoded = bytesNeeded;
162 ret = TRUE;
164 else if (*pcbEncoded < bytesNeeded)
166 SetLastError(ERROR_MORE_DATA);
167 *pcbEncoded = bytesNeeded;
169 else
171 *pcbEncoded = bytesNeeded;
172 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
173 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
174 &lenBytes);
175 pbEncoded += lenBytes;
176 *pbEncoded++ = ASN_CONTEXT;
177 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
178 pbEncoded += fileNameLenBytes;
179 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
181 *(WCHAR *)pbEncoded = hton16(*ptr);
182 pbEncoded += sizeof(WCHAR);
184 ret = TRUE;
186 break;
188 case SPC_MONIKER_LINK_CHOICE:
190 DWORD classIdLenBytes, dataLenBytes, dataLen;
191 CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
192 (BYTE *)link->u.Moniker.ClassId };
194 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
195 CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
196 &dataLenBytes);
197 dataLen = 2 + classIdLenBytes + classId.cbData +
198 dataLenBytes + link->u.Moniker.SerializedData.cbData;
199 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
200 bytesNeeded = 1 + dataLen + lenBytes;
201 if (!pbEncoded)
203 *pcbEncoded = bytesNeeded;
204 ret = TRUE;
206 else if (*pcbEncoded < bytesNeeded)
208 SetLastError(ERROR_MORE_DATA);
209 *pcbEncoded = bytesNeeded;
211 else
213 DWORD size;
215 *pcbEncoded = bytesNeeded;
216 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
217 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
218 pbEncoded += lenBytes;
219 size = 1 + classIdLenBytes + classId.cbData;
220 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
221 pbEncoded, &size);
222 pbEncoded += size;
223 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
224 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
225 &link->u.Moniker.SerializedData, pbEncoded, &size);
226 pbEncoded += size;
227 ret = TRUE;
229 break;
231 case SPC_URL_LINK_CHOICE:
233 LPWSTR ptr;
234 DWORD urlLen;
236 /* Check for invalid characters in URL */
237 ret = TRUE;
238 urlLen = 0;
239 for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
240 if (*ptr > 0x7f)
242 *pcbEncoded = 0;
243 SetLastError(CRYPT_E_INVALID_IA5_STRING);
244 ret = FALSE;
246 else
247 urlLen++;
248 if (ret)
250 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
251 bytesNeeded = 1 + lenBytes + urlLen;
252 if (!pbEncoded)
253 *pcbEncoded = bytesNeeded;
254 else if (*pcbEncoded < bytesNeeded)
256 SetLastError(ERROR_MORE_DATA);
257 *pcbEncoded = bytesNeeded;
258 ret = FALSE;
260 else
262 *pcbEncoded = bytesNeeded;
263 *pbEncoded++ = ASN_CONTEXT;
264 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
265 pbEncoded += lenBytes;
266 for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
267 *pbEncoded++ = (BYTE)*ptr;
270 break;
272 default:
273 SetLastError(E_INVALIDARG);
276 __EXCEPT_PAGE_FAULT
278 SetLastError(STATUS_ACCESS_VIOLATION);
280 __ENDTRY
281 TRACE("returning %d\n", ret);
282 return ret;
285 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
286 BYTE *, DWORD *);
288 struct AsnEncodeSequenceItem
290 const void *pvStructInfo;
291 CryptEncodeObjectFunc encodeFunc;
292 DWORD size; /* used during encoding, not for your use */
295 static BOOL CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
296 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
297 DWORD *pcbEncoded)
299 BOOL ret;
300 DWORD i, dataLen = 0;
302 TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
303 for (i = 0, ret = TRUE; ret && i < cItem; i++)
305 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
306 items[i].pvStructInfo, NULL, &items[i].size);
307 /* Some functions propagate their errors through the size */
308 if (!ret)
309 *pcbEncoded = items[i].size;
310 dataLen += items[i].size;
312 if (ret)
314 DWORD lenBytes, bytesNeeded;
316 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
317 bytesNeeded = 1 + lenBytes + dataLen;
318 if (!pbEncoded)
319 *pcbEncoded = bytesNeeded;
320 else if (*pcbEncoded < bytesNeeded)
322 *pcbEncoded = bytesNeeded;
323 SetLastError(ERROR_MORE_DATA);
324 ret = FALSE;
326 else
328 *pcbEncoded = bytesNeeded;
329 *pbEncoded++ = ASN_SEQUENCE;
330 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
331 pbEncoded += lenBytes;
332 for (i = 0; ret && i < cItem; i++)
334 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
335 items[i].pvStructInfo, pbEncoded, &items[i].size);
336 /* Some functions propagate their errors through the size */
337 if (!ret)
338 *pcbEncoded = items[i].size;
339 pbEncoded += items[i].size;
343 TRACE("returning %d\n", ret);
344 return ret;
347 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
348 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
349 DWORD *pcbEncoded)
351 BOOL ret = FALSE;
353 __TRY
355 const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
356 DWORD bytesNeeded, lenBytes, dataBytes;
357 BYTE unusedBits;
359 /* yep, MS allows cUnusedBits to be >= 8 */
360 if (!blob->cUnusedBits)
362 dataBytes = blob->cbData;
363 unusedBits = 0;
365 else if (blob->cbData * 8 > blob->cUnusedBits)
367 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
368 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
369 blob->cUnusedBits;
371 else
373 dataBytes = 0;
374 unusedBits = 0;
376 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
377 bytesNeeded = 1 + lenBytes + dataBytes + 1;
378 if (!pbEncoded)
380 *pcbEncoded = bytesNeeded;
381 ret = TRUE;
383 else if (*pcbEncoded < bytesNeeded)
385 *pcbEncoded = bytesNeeded;
386 SetLastError(ERROR_MORE_DATA);
388 else
390 ret = TRUE;
391 *pcbEncoded = bytesNeeded;
392 *pbEncoded++ = ASN_BITSTRING;
393 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
394 pbEncoded += lenBytes;
395 *pbEncoded++ = unusedBits;
396 if (dataBytes)
398 BYTE mask = 0xff << unusedBits;
400 if (dataBytes > 1)
402 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
403 pbEncoded += dataBytes - 1;
405 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
409 __EXCEPT_PAGE_FAULT
411 SetLastError(STATUS_ACCESS_VIOLATION);
413 __ENDTRY
414 return ret;
417 struct AsnConstructedItem
419 BYTE tag;
420 const void *pvStructInfo;
421 CryptEncodeObjectFunc encodeFunc;
424 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
425 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
426 DWORD *pcbEncoded)
428 BOOL ret;
429 const struct AsnConstructedItem *item =
430 (const struct AsnConstructedItem *)pvStructInfo;
431 DWORD len;
433 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
434 item->pvStructInfo, NULL, &len)))
436 DWORD dataLen, bytesNeeded;
438 CRYPT_EncodeLen(len, NULL, &dataLen);
439 bytesNeeded = 1 + dataLen + len;
440 if (!pbEncoded)
441 *pcbEncoded = bytesNeeded;
442 else if (*pcbEncoded < bytesNeeded)
444 *pcbEncoded = bytesNeeded;
445 SetLastError(ERROR_MORE_DATA);
446 ret = FALSE;
448 else
450 *pcbEncoded = bytesNeeded;
451 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
452 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
453 pbEncoded += dataLen;
454 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
455 item->pvStructInfo, pbEncoded, &len);
456 if (!ret)
458 /* Some functions propagate their errors through the size */
459 *pcbEncoded = len;
463 else
465 /* Some functions propagate their errors through the size */
466 *pcbEncoded = len;
468 return ret;
472 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
473 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
474 DWORD *pcbEncoded)
476 const SPC_PE_IMAGE_DATA *imageData =
477 (const SPC_PE_IMAGE_DATA *)pvStructInfo;
478 BOOL ret = FALSE;
480 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
481 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
482 pcbEncoded);
484 __TRY
486 struct AsnEncodeSequenceItem items[2] = {
487 { 0 }
489 struct AsnConstructedItem constructed = { 0, imageData->pFile,
490 WVTAsn1SpcLinkEncode };
491 DWORD cItem = 0;
493 if (imageData->Flags.cbData)
495 items[cItem].pvStructInfo = &imageData->Flags;
496 items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
497 cItem++;
499 if (imageData->pFile)
501 items[cItem].pvStructInfo = &constructed;
502 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
503 cItem++;
506 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
507 pbEncoded, pcbEncoded);
509 __EXCEPT_PAGE_FAULT
511 SetLastError(STATUS_ACCESS_VIOLATION);
513 __ENDTRY
514 TRACE("returning %d\n", ret);
515 return ret;
518 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
519 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
520 DWORD *pcbEncoded)
522 LPCSTR pszObjId = (LPCSTR)pvStructInfo;
523 DWORD bytesNeeded = 0, lenBytes;
524 BOOL ret = TRUE;
525 int firstPos = 0;
526 BYTE firstByte = 0;
528 TRACE("%s\n", debugstr_a(pszObjId));
530 if (pszObjId)
532 const char *ptr;
533 int val1, val2;
535 if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
537 SetLastError(CRYPT_E_ASN1_ERROR);
538 return FALSE;
540 bytesNeeded++;
541 firstByte = val1 * 40 + val2;
542 ptr = pszObjId + firstPos;
543 while (ret && *ptr)
545 int pos;
547 /* note I assume each component is at most 32-bits long in base 2 */
548 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
550 if (val1 >= 0x10000000)
551 bytesNeeded += 5;
552 else if (val1 >= 0x200000)
553 bytesNeeded += 4;
554 else if (val1 >= 0x4000)
555 bytesNeeded += 3;
556 else if (val1 >= 0x80)
557 bytesNeeded += 2;
558 else
559 bytesNeeded += 1;
560 ptr += pos;
561 if (*ptr == '.')
562 ptr++;
564 else
566 SetLastError(CRYPT_E_ASN1_ERROR);
567 return FALSE;
570 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
572 else
573 lenBytes = 1;
574 bytesNeeded += 1 + lenBytes;
575 if (pbEncoded)
577 if (*pcbEncoded < bytesNeeded)
579 SetLastError(ERROR_MORE_DATA);
580 ret = FALSE;
582 else
584 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
585 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
586 pbEncoded += lenBytes;
587 if (pszObjId)
589 const char *ptr;
590 int val, pos;
592 *pbEncoded++ = firstByte;
593 ptr = pszObjId + firstPos;
594 while (ret && *ptr)
596 sscanf(ptr, "%d%n", &val, &pos);
598 unsigned char outBytes[5];
599 int numBytes, i;
601 if (val >= 0x10000000)
602 numBytes = 5;
603 else if (val >= 0x200000)
604 numBytes = 4;
605 else if (val >= 0x4000)
606 numBytes = 3;
607 else if (val >= 0x80)
608 numBytes = 2;
609 else
610 numBytes = 1;
611 for (i = numBytes; i > 0; i--)
613 outBytes[i - 1] = val & 0x7f;
614 val >>= 7;
616 for (i = 0; i < numBytes - 1; i++)
617 *pbEncoded++ = outBytes[i] | 0x80;
618 *pbEncoded++ = outBytes[i];
619 ptr += pos;
620 if (*ptr == '.')
621 ptr++;
627 *pcbEncoded = bytesNeeded;
628 return ret;
631 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
632 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
633 DWORD *pcbEncoded)
635 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
636 BOOL ret = TRUE;
638 if (!pbEncoded)
639 *pcbEncoded = blob->cbData;
640 else if (*pcbEncoded < blob->cbData)
642 *pcbEncoded = blob->cbData;
643 SetLastError(ERROR_MORE_DATA);
644 ret = FALSE;
646 else
648 if (blob->cbData)
649 memcpy(pbEncoded, blob->pbData, blob->cbData);
650 *pcbEncoded = blob->cbData;
652 return ret;
655 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
656 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
657 BYTE *pbEncoded, DWORD *pcbEncoded)
659 const CRYPT_ALGORITHM_IDENTIFIER *algo =
660 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
661 static const BYTE asn1Null[] = { ASN_NULL, 0 };
662 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
663 (LPBYTE)asn1Null };
664 BOOL ret;
665 struct AsnEncodeSequenceItem items[2] = {
666 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
667 { NULL, CRYPT_CopyEncodedBlob, 0 },
670 if (algo->Parameters.cbData)
671 items[1].pvStructInfo = &algo->Parameters;
672 else
673 items[1].pvStructInfo = &nullBlob;
674 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
675 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
676 return ret;
679 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
680 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
681 DWORD *pcbEncoded)
683 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
684 (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
685 struct AsnEncodeSequenceItem items[] = {
686 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
687 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
690 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
691 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
694 struct SPCDigest
696 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
697 CRYPT_HASH_BLOB Digest;
700 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
701 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
702 DWORD *pcbEncoded)
704 const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
705 struct AsnEncodeSequenceItem items[] = {
706 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
707 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 },
710 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
711 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
714 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
716 DWORD *pcbEncoded)
718 BOOL ret = FALSE;
720 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
721 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
723 __TRY
725 const SPC_INDIRECT_DATA_CONTENT *data =
726 (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
727 struct AsnEncodeSequenceItem items[] = {
728 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
729 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
732 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
733 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
735 __EXCEPT_PAGE_FAULT
737 SetLastError(STATUS_ACCESS_VIOLATION);
739 __ENDTRY
740 return ret;
743 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
744 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
745 DWORD *pcbEncoded)
747 BOOL ret = TRUE;
748 LPCWSTR str = (LPCWSTR)pvStructInfo;
749 DWORD bytesNeeded, lenBytes, strLen;
751 if (str)
752 strLen = lstrlenW(str);
753 else
754 strLen = 0;
755 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
756 bytesNeeded = 1 + lenBytes + strLen * 2;
757 if (!pbEncoded)
758 *pcbEncoded = bytesNeeded;
759 else if (*pcbEncoded < bytesNeeded)
761 *pcbEncoded = bytesNeeded;
762 SetLastError(ERROR_MORE_DATA);
763 ret = FALSE;
765 else
767 DWORD i;
769 *pcbEncoded = bytesNeeded;
770 *pbEncoded++ = ASN_BMPSTRING;
771 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
772 pbEncoded += lenBytes;
773 for (i = 0; i < strLen; i++)
775 *pbEncoded++ = (str[i] & 0xff00) >> 8;
776 *pbEncoded++ = str[i] & 0x00ff;
779 return ret;
782 struct AsnEncodeTagSwappedItem
784 BYTE tag;
785 const void *pvStructInfo;
786 CryptEncodeObjectFunc encodeFunc;
789 /* Sort of a wacky hack, it encodes something using the struct
790 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
791 * given in the struct AsnEncodeTagSwappedItem.
793 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
794 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
795 DWORD *pcbEncoded)
797 BOOL ret;
798 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
800 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
801 item->pvStructInfo, pbEncoded, pcbEncoded);
802 if (ret && pbEncoded)
803 *pbEncoded = item->tag;
804 return ret;
807 BOOL WINAPI WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType,
808 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
809 DWORD *pcbEncoded)
811 BOOL ret = FALSE;
813 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
814 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
816 __TRY
818 const SPC_SP_OPUS_INFO *info = pvStructInfo;
820 if (info->pMoreInfo &&
821 info->pMoreInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
822 info->pMoreInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
823 info->pMoreInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
824 SetLastError(E_INVALIDARG);
825 else if (info->pPublisherInfo &&
826 info->pPublisherInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
827 info->pPublisherInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
828 info->pPublisherInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
829 SetLastError(E_INVALIDARG);
830 else
832 struct AsnEncodeSequenceItem items[3] = { { 0 } };
833 struct AsnConstructedItem constructed[3] = { { 0 } };
834 struct AsnEncodeTagSwappedItem swapped;
835 DWORD cItem = 0, cConstructed = 0;
837 if (info->pwszProgramName)
839 swapped.tag = ASN_CONTEXT;
840 swapped.pvStructInfo = info->pwszProgramName;
841 swapped.encodeFunc = CRYPT_AsnEncodeBMPString;
842 constructed[cConstructed].tag = 0;
843 constructed[cConstructed].pvStructInfo = &swapped;
844 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeSwapTag;
845 items[cItem].pvStructInfo = &constructed[cConstructed];
846 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
847 cConstructed++;
848 cItem++;
850 if (info->pMoreInfo)
852 constructed[cConstructed].tag = 1;
853 constructed[cConstructed].pvStructInfo = info->pMoreInfo;
854 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
855 items[cItem].pvStructInfo = &constructed[cConstructed];
856 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
857 cConstructed++;
858 cItem++;
860 if (info->pPublisherInfo)
862 constructed[cConstructed].tag = 2;
863 constructed[cConstructed].pvStructInfo = info->pPublisherInfo;
864 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
865 items[cItem].pvStructInfo = &constructed[cConstructed];
866 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
867 cConstructed++;
868 cItem++;
870 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
871 items, cItem, pbEncoded, pcbEncoded);
874 __EXCEPT_PAGE_FAULT
876 SetLastError(STATUS_ACCESS_VIOLATION);
878 __ENDTRY
879 return ret;
882 static BOOL CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
883 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
884 DWORD *pcbEncoded)
886 BOOL ret;
888 __TRY
890 DWORD significantBytes, lenBytes, bytesNeeded;
891 BYTE padByte = 0;
892 BOOL pad = FALSE;
893 const CRYPT_INTEGER_BLOB *blob =
894 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
896 significantBytes = blob->cbData;
897 if (significantBytes)
899 if (blob->pbData[significantBytes - 1] & 0x80)
901 /* negative, lop off leading (little-endian) 0xffs */
902 for (; significantBytes > 0 &&
903 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
905 if (blob->pbData[significantBytes - 1] < 0x80)
907 padByte = 0xff;
908 pad = TRUE;
911 else
913 /* positive, lop off leading (little-endian) zeroes */
914 for (; significantBytes > 0 &&
915 !blob->pbData[significantBytes - 1]; significantBytes--)
917 if (significantBytes == 0)
918 significantBytes = 1;
919 if (blob->pbData[significantBytes - 1] > 0x7f)
921 padByte = 0;
922 pad = TRUE;
926 if (pad)
927 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
928 else
929 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
930 bytesNeeded = 1 + lenBytes + significantBytes;
931 if (pad)
932 bytesNeeded++;
933 if (!pbEncoded)
935 *pcbEncoded = bytesNeeded;
936 ret = TRUE;
938 else if (*pcbEncoded < bytesNeeded)
940 *pcbEncoded = bytesNeeded;
941 SetLastError(ERROR_MORE_DATA);
942 ret = FALSE;
944 else
946 *pcbEncoded = bytesNeeded;
947 *pbEncoded++ = ASN_INTEGER;
948 if (pad)
950 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
951 pbEncoded += lenBytes;
952 *pbEncoded++ = padByte;
954 else
956 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
957 pbEncoded += lenBytes;
959 for (; significantBytes > 0; significantBytes--)
960 *(pbEncoded++) = blob->pbData[significantBytes - 1];
961 ret = TRUE;
964 __EXCEPT_PAGE_FAULT
966 SetLastError(STATUS_ACCESS_VIOLATION);
967 ret = FALSE;
969 __ENDTRY
970 return ret;
973 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
974 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
975 DWORD *pcbEncoded)
977 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
979 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
980 &blob, pbEncoded, pcbEncoded);
983 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
984 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
985 DWORD *pcbEncoded)
987 BOOL ret = FALSE;
989 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
990 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
992 __TRY
994 const CAT_MEMBERINFO *info = (const CAT_MEMBERINFO *)pvStructInfo;
995 struct AsnEncodeSequenceItem items[] = {
996 { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
997 { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
1000 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1001 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1003 __EXCEPT_PAGE_FAULT
1005 SetLastError(STATUS_ACCESS_VIOLATION);
1007 __ENDTRY
1008 return ret;
1011 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
1012 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1013 DWORD *pcbEncoded)
1015 BOOL ret = FALSE;
1017 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
1018 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1020 __TRY
1022 const CAT_NAMEVALUE *value = (const CAT_NAMEVALUE *)pvStructInfo;
1023 struct AsnEncodeSequenceItem items[] = {
1024 { value->pwszTag, CRYPT_AsnEncodeBMPString, 0 },
1025 { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
1026 { &value->Value, CRYPT_AsnEncodeOctets, 0 },
1029 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1030 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1032 __EXCEPT_PAGE_FAULT
1034 SetLastError(STATUS_ACCESS_VIOLATION);
1036 __ENDTRY
1037 return ret;
1040 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1041 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1042 DWORD *pcbEncoded)
1044 BOOL val = *(const BOOL *)pvStructInfo, ret;
1046 TRACE("%d\n", val);
1048 if (!pbEncoded)
1050 *pcbEncoded = 3;
1051 ret = TRUE;
1053 else if (*pcbEncoded < 3)
1055 *pcbEncoded = 3;
1056 SetLastError(ERROR_MORE_DATA);
1057 ret = FALSE;
1059 else
1061 *pcbEncoded = 3;
1062 *pbEncoded++ = ASN_BOOL;
1063 *pbEncoded++ = 1;
1064 *pbEncoded++ = val ? 0xff : 0;
1065 ret = TRUE;
1067 TRACE("returning %d (%08x)\n", ret, GetLastError());
1068 return ret;
1071 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType,
1072 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1073 DWORD *pcbEncoded)
1075 BOOL ret = FALSE;
1077 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
1078 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1080 __TRY
1082 const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo;
1083 struct AsnEncodeSequenceItem items[] = {
1084 { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 },
1085 { &criteria->fMeetsCriteria, CRYPT_AsnEncodeBool, 0 },
1088 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1089 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1091 __EXCEPT_PAGE_FAULT
1093 SetLastError(STATUS_ACCESS_VIOLATION);
1095 __ENDTRY
1096 return ret;
1099 /* Gets the number of length bytes from the given (leading) length byte */
1100 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1102 /* Helper function to get the encoded length of the data starting at pbEncoded,
1103 * where pbEncoded[0] is the tag. If the data are too short to contain a
1104 * length or if the length is too large for cbEncoded, sets an appropriate
1105 * error code and returns FALSE.
1107 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
1109 BOOL ret;
1111 if (cbEncoded <= 1)
1113 SetLastError(CRYPT_E_ASN1_CORRUPT);
1114 ret = FALSE;
1116 else if (pbEncoded[1] <= 0x7f)
1118 if (pbEncoded[1] + 1 > cbEncoded)
1120 SetLastError(CRYPT_E_ASN1_EOD);
1121 ret = FALSE;
1123 else
1125 *len = pbEncoded[1];
1126 ret = TRUE;
1129 else if (pbEncoded[1] == 0x80)
1131 FIXME("unimplemented for indefinite-length encoding\n");
1132 SetLastError(CRYPT_E_ASN1_CORRUPT);
1133 ret = FALSE;
1135 else
1137 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
1139 if (lenLen > sizeof(DWORD) + 1)
1141 SetLastError(CRYPT_E_ASN1_LARGE);
1142 ret = FALSE;
1144 else if (lenLen + 2 > cbEncoded)
1146 SetLastError(CRYPT_E_ASN1_CORRUPT);
1147 ret = FALSE;
1149 else
1151 DWORD out = 0;
1153 pbEncoded += 2;
1154 while (--lenLen)
1156 out <<= 8;
1157 out |= *pbEncoded++;
1159 if (out + lenLen + 1 > cbEncoded)
1161 SetLastError(CRYPT_E_ASN1_EOD);
1162 ret = FALSE;
1164 else
1166 *len = out;
1167 ret = TRUE;
1171 return ret;
1174 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1175 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1176 void *pvStructInfo, DWORD *pcbStructInfo)
1178 BOOL ret;
1179 DWORD bytesNeeded, dataLen;
1181 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1182 pvStructInfo, *pcbStructInfo);
1184 if (!cbEncoded)
1186 SetLastError(CRYPT_E_ASN1_CORRUPT);
1187 ret = FALSE;
1189 else if (pbEncoded[0] != ASN_OCTETSTRING)
1191 SetLastError(CRYPT_E_ASN1_BADTAG);
1192 ret = FALSE;
1194 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1196 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1197 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1198 else
1199 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1200 if (!pvStructInfo)
1201 *pcbStructInfo = bytesNeeded;
1202 else if (*pcbStructInfo < bytesNeeded)
1204 SetLastError(ERROR_MORE_DATA);
1205 *pcbStructInfo = bytesNeeded;
1206 ret = FALSE;
1208 else
1210 CRYPT_DATA_BLOB *blob;
1211 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1213 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1214 blob->cbData = dataLen;
1215 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1216 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1217 else
1219 assert(blob->pbData);
1220 if (blob->cbData)
1221 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1222 blob->cbData);
1226 return ret;
1229 static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
1230 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1231 void *pvStructInfo, DWORD *pcbStructInfo)
1233 BOOL ret = FALSE;
1234 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
1236 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1237 pvStructInfo, *pcbStructInfo);
1239 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1241 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1242 DWORD realDataLen;
1244 switch (pbEncoded[0])
1246 case ASN_CONTEXT:
1247 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1248 if (!pvStructInfo)
1249 *pcbStructInfo = bytesNeeded;
1250 else if (*pcbStructInfo < bytesNeeded)
1252 *pcbStructInfo = bytesNeeded;
1253 SetLastError(ERROR_MORE_DATA);
1254 ret = FALSE;
1256 else
1258 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1259 DWORD i;
1261 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
1262 for (i = 0; i < dataLen; i++)
1263 link->u.pwszUrl[i] =
1264 *(pbEncoded + 1 + lenBytes + i);
1265 link->u.pwszUrl[i] = '\0';
1266 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
1268 break;
1269 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
1271 CRYPT_DATA_BLOB classId;
1272 DWORD size = sizeof(classId);
1274 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1275 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
1276 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
1278 if (classId.cbData != sizeof(SPC_UUID))
1280 SetLastError(CRYPT_E_BAD_ENCODE);
1281 ret = FALSE;
1283 else
1285 CRYPT_DATA_BLOB data;
1287 /* The tag length for the classId must be 1 since the
1288 * length is correct.
1290 size = sizeof(data);
1291 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1292 pbEncoded + 3 + lenBytes + classId.cbData,
1293 cbEncoded - 3 - lenBytes - classId.cbData,
1294 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
1296 bytesNeeded += data.cbData;
1297 if (!pvStructInfo)
1298 *pcbStructInfo = bytesNeeded;
1299 else if (*pcbStructInfo < bytesNeeded)
1301 *pcbStructInfo = bytesNeeded;
1302 SetLastError(ERROR_MORE_DATA);
1303 ret = FALSE;
1305 else
1307 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1309 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
1310 /* pwszFile pointer was set by caller, copy it
1311 * before overwriting it
1313 link->u.Moniker.SerializedData.pbData =
1314 (BYTE *)link->u.pwszFile;
1315 memcpy(link->u.Moniker.ClassId, classId.pbData,
1316 classId.cbData);
1317 memcpy(link->u.Moniker.SerializedData.pbData,
1318 data.pbData, data.cbData);
1319 link->u.Moniker.SerializedData.cbData = data.cbData;
1324 break;
1326 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
1327 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
1328 SetLastError(CRYPT_E_ASN1_BADTAG);
1329 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
1330 &realDataLen)))
1332 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
1334 bytesNeeded += realDataLen + sizeof(WCHAR);
1335 if (!pvStructInfo)
1336 *pcbStructInfo = bytesNeeded;
1337 else if (*pcbStructInfo < bytesNeeded)
1339 *pcbStructInfo = bytesNeeded;
1340 SetLastError(ERROR_MORE_DATA);
1341 ret = FALSE;
1343 else
1345 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1346 DWORD i;
1347 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
1349 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1350 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
1351 link->u.pwszFile[i] =
1352 hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
1353 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
1354 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
1357 else
1359 bytesNeeded += sizeof(WCHAR);
1360 if (!pvStructInfo)
1361 *pcbStructInfo = bytesNeeded;
1362 else if (*pcbStructInfo < bytesNeeded)
1364 *pcbStructInfo = bytesNeeded;
1365 SetLastError(ERROR_MORE_DATA);
1366 ret = FALSE;
1368 else
1370 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1372 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1373 link->u.pwszFile[0] = '\0';
1374 ret = TRUE;
1377 break;
1378 default:
1379 SetLastError(CRYPT_E_ASN1_BADTAG);
1382 TRACE("returning %d\n", ret);
1383 return ret;
1386 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1388 void *pvStructInfo, DWORD *pcbStructInfo)
1390 BOOL ret = FALSE;
1392 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1393 pvStructInfo, *pcbStructInfo);
1395 __TRY
1397 DWORD bytesNeeded;
1399 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1400 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1401 if (ret)
1403 if (!pvStructInfo)
1404 *pcbStructInfo = bytesNeeded;
1405 else if (*pcbStructInfo < bytesNeeded)
1407 *pcbStructInfo = bytesNeeded;
1408 SetLastError(ERROR_MORE_DATA);
1409 ret = FALSE;
1411 else
1413 SPC_LINK *link = (SPC_LINK *)pvStructInfo;
1415 link->u.pwszFile =
1416 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1417 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1418 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1419 pcbStructInfo);
1423 __EXCEPT_PAGE_FAULT
1425 SetLastError(STATUS_ACCESS_VIOLATION);
1427 __ENDTRY
1428 TRACE("returning %d\n", ret);
1429 return ret;
1432 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1433 DWORD, DWORD, void *, DWORD *);
1435 /* tag:
1436 * The expected tag of the item. If tag is 0, decodeFunc is called
1437 * regardless of the tag value seen.
1438 * offset:
1439 * A sequence is decoded into a struct. The offset member is the
1440 * offset of this item within that struct.
1441 * decodeFunc:
1442 * The decoder function to use. If this is NULL, then the member isn't
1443 * decoded, but minSize space is reserved for it.
1444 * minSize:
1445 * The minimum amount of space occupied after decoding. You must set this.
1446 * optional:
1447 * If true, and the tag doesn't match the expected tag for this item,
1448 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1449 * filled with 0 for this member.
1450 * hasPointer, pointerOffset:
1451 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1452 * the offset within the struct of the data pointer (or to the
1453 * first data pointer, if more than one exist).
1454 * size:
1455 * Used by CRYPT_AsnDecodeSequence, not for your use.
1457 struct AsnDecodeSequenceItem
1459 BYTE tag;
1460 DWORD offset;
1461 CryptDecodeObjectFunc decodeFunc;
1462 DWORD minSize;
1463 BOOL optional;
1464 BOOL hasPointer;
1465 DWORD pointerOffset;
1466 DWORD size;
1469 /* Decodes the items in a sequence, where the items are described in items,
1470 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1471 * pvStructInfo. nextData is a pointer to the memory location at which the
1472 * first decoded item with a dynamic pointer should point.
1473 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1475 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1476 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1477 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1478 DWORD *cbDecoded)
1480 BOOL ret;
1481 DWORD i, decoded = 0;
1482 const BYTE *ptr = pbEncoded;
1484 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1485 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1487 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1489 if (cbEncoded - (ptr - pbEncoded) != 0)
1491 DWORD nextItemLen;
1493 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1494 &nextItemLen)))
1496 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1498 if (ptr[0] == items[i].tag || !items[i].tag)
1500 if (nextData && pvStructInfo && items[i].hasPointer)
1502 TRACE("Setting next pointer to %p\n",
1503 nextData);
1504 *(BYTE **)((BYTE *)pvStructInfo +
1505 items[i].pointerOffset) = nextData;
1507 if (items[i].decodeFunc)
1509 if (pvStructInfo)
1510 TRACE("decoding item %d\n", i);
1511 else
1512 TRACE("sizing item %d\n", i);
1513 ret = items[i].decodeFunc(dwCertEncodingType,
1514 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1515 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1516 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1517 : NULL, &items[i].size);
1518 if (ret)
1520 /* Account for alignment padding */
1521 if (items[i].size % sizeof(DWORD))
1522 items[i].size += sizeof(DWORD) -
1523 items[i].size % sizeof(DWORD);
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);
1539 ret = TRUE;
1541 else
1542 TRACE("item %d failed: %08x\n", i,
1543 GetLastError());
1545 else
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;
1559 else
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);
1564 ret = FALSE;
1568 else if (items[i].optional)
1570 TRACE("missing optional item %d, skipping\n", i);
1571 items[i].size = items[i].minSize;
1573 else
1575 TRACE("not enough bytes for item %d, failing\n", i);
1576 SetLastError(CRYPT_E_ASN1_CORRUPT);
1577 ret = FALSE;
1580 if (ret)
1581 *cbDecoded = decoded;
1582 TRACE("returning %d\n", ret);
1583 return 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)
1598 BOOL ret;
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)
1605 DWORD dataLen;
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,
1616 cbEncoded);
1617 SetLastError(CRYPT_E_ASN1_CORRUPT);
1618 ret = FALSE;
1620 else
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,
1626 cbDecoded);
1627 SetLastError(CRYPT_E_ASN1_CORRUPT);
1628 ret = FALSE;
1630 if (ret)
1632 DWORD i, bytesNeeded = 0, structSize = 0;
1634 for (i = 0; i < cItem; i++)
1636 bytesNeeded += items[i].size;
1637 structSize += items[i].minSize;
1639 if (!pvStructInfo)
1640 *pcbStructInfo = bytesNeeded;
1641 else if (*pcbStructInfo < bytesNeeded)
1643 SetLastError(ERROR_MORE_DATA);
1644 *pcbStructInfo = bytesNeeded;
1645 ret = FALSE;
1647 else
1649 BYTE *nextData;
1651 *pcbStructInfo = bytesNeeded;
1652 if (startingPointer)
1653 nextData = (BYTE *)startingPointer;
1654 else
1655 nextData = (BYTE *)pvStructInfo + structSize;
1656 memset(pvStructInfo, 0, structSize);
1657 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1658 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1659 &cbDecoded);
1664 else
1666 SetLastError(CRYPT_E_ASN1_BADTAG);
1667 ret = FALSE;
1669 TRACE("returning %d (%08x)\n", ret, GetLastError());
1670 return ret;
1673 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1674 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1675 void *pvStructInfo, DWORD *pcbStructInfo)
1677 BOOL ret;
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);
1690 else
1691 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1692 if (!pvStructInfo)
1693 *pcbStructInfo = bytesNeeded;
1694 else if (*pcbStructInfo < bytesNeeded)
1696 *pcbStructInfo = bytesNeeded;
1697 SetLastError(ERROR_MORE_DATA);
1698 ret = FALSE;
1700 else
1702 CRYPT_BIT_BLOB *blob;
1704 blob = (CRYPT_BIT_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]);
1713 else
1715 assert(blob->pbData);
1716 if (blob->cbData)
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;
1728 else
1730 SetLastError(CRYPT_E_ASN1_BADTAG);
1731 ret = FALSE;
1733 TRACE("returning %d (%08x)\n", ret, GetLastError());
1734 return ret;
1737 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1738 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1739 void *pvStructInfo, DWORD *pcbStructInfo)
1741 BOOL ret = FALSE;
1742 DWORD dataLen;
1744 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1746 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1747 DWORD size;
1748 SPC_LINK **pLink = (SPC_LINK **)pvStructInfo;
1750 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1751 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1752 if (ret)
1754 if (!pvStructInfo)
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);
1760 ret = FALSE;
1762 else
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);
1777 return ret;
1780 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1781 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1782 void *pvStructInfo, DWORD *pcbStructInfo)
1784 BOOL ret = FALSE;
1786 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1787 pvStructInfo, *pcbStructInfo);
1789 __TRY
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);
1804 __EXCEPT_PAGE_FAULT
1806 SetLastError(STATUS_ACCESS_VIOLATION);
1808 __ENDTRY
1809 TRACE("returning %d\n", ret);
1810 return ret;
1813 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1814 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1815 void *pvStructInfo, DWORD *pcbStructInfo)
1817 BOOL ret = TRUE;
1818 DWORD dataLen;
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);
1828 if (dataLen)
1830 /* The largest possible string for the first two components
1831 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1833 char firstTwo[6];
1834 const BYTE *ptr;
1836 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1837 pbEncoded[1 + lenBytes] / 40,
1838 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1839 * 40);
1840 bytesNeeded += strlen(firstTwo) + 1;
1841 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1842 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1844 /* large enough for ".4000000" */
1845 char str[9];
1846 int val = 0;
1848 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1849 (*ptr & 0x80))
1851 val <<= 7;
1852 val |= *ptr & 0x7f;
1853 ptr++;
1855 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1856 (*ptr & 0x80))
1858 SetLastError(CRYPT_E_ASN1_CORRUPT);
1859 ret = FALSE;
1861 else
1863 val <<= 7;
1864 val |= *ptr++;
1865 snprintf(str, sizeof(str), ".%d", val);
1866 bytesNeeded += strlen(str);
1870 if (!pvStructInfo)
1871 *pcbStructInfo = bytesNeeded;
1872 else if (*pcbStructInfo < bytesNeeded)
1874 *pcbStructInfo = bytesNeeded;
1875 SetLastError(ERROR_MORE_DATA);
1876 ret = FALSE;
1878 else
1880 if (dataLen)
1882 const BYTE *ptr;
1883 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1885 *pszObjId = 0;
1886 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1887 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1888 40) * 40);
1889 pszObjId += strlen(pszObjId);
1890 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1891 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1893 int val = 0;
1895 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1896 (*ptr & 0x80))
1898 val <<= 7;
1899 val |= *ptr & 0x7f;
1900 ptr++;
1902 val <<= 7;
1903 val |= *ptr++;
1904 sprintf(pszObjId, ".%d", val);
1905 pszObjId += strlen(pszObjId);
1908 else
1909 *(LPSTR *)pvStructInfo = NULL;
1910 *pcbStructInfo = bytesNeeded;
1913 return ret;
1916 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1917 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1918 void *pvStructInfo, DWORD *pcbStructInfo)
1920 BOOL ret = FALSE;
1922 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1923 pvStructInfo, *pcbStructInfo);
1925 if (!cbEncoded)
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);
1930 else
1931 SetLastError(CRYPT_E_ASN1_BADTAG);
1932 return ret;
1935 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1936 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1937 void *pvStructInfo, DWORD *pcbStructInfo)
1939 BOOL ret = TRUE;
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;
1947 if (!pvStructInfo)
1948 *pcbStructInfo = bytesNeeded;
1949 else if (*pcbStructInfo < bytesNeeded)
1951 SetLastError(ERROR_MORE_DATA);
1952 *pcbStructInfo = bytesNeeded;
1953 ret = FALSE;
1955 else
1957 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1959 *pcbStructInfo = bytesNeeded;
1960 blob->cbData = cbEncoded;
1961 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1962 blob->pbData = (LPBYTE)pbEncoded;
1963 else
1965 assert(blob->pbData);
1966 memcpy(blob->pbData, pbEncoded, blob->cbData);
1969 return ret;
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 =
1977 (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
1978 struct AsnDecodeSequenceItem items[] = {
1979 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1980 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1981 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1982 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1983 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1984 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1987 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1988 pvStructInfo, *pcbStructInfo);
1990 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1991 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1992 pvStructInfo, pcbStructInfo,
1993 typeValue ? typeValue->pszObjId : NULL);
1996 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1997 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1998 void *pvStructInfo, DWORD *pcbStructInfo)
2000 CRYPT_ALGORITHM_IDENTIFIER *algo =
2001 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2002 BOOL ret = TRUE;
2003 struct AsnDecodeSequenceItem items[] = {
2004 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2005 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2006 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2007 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2008 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2009 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2012 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2013 pvStructInfo, *pcbStructInfo);
2015 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2016 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2017 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
2018 if (ret && pvStructInfo)
2020 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2021 debugstr_a(algo->pszObjId));
2023 return ret;
2026 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
2027 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2028 void *pvStructInfo, DWORD *pcbStructInfo)
2030 struct SPCDigest *digest =
2031 (struct SPCDigest *)pvStructInfo;
2032 struct AsnDecodeSequenceItem items[] = {
2033 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
2034 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2035 FALSE, TRUE,
2036 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
2037 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
2038 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
2039 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
2042 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2043 pvStructInfo, *pcbStructInfo);
2045 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2046 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2047 pvStructInfo, pcbStructInfo,
2048 digest ? digest->DigestAlgorithm.pszObjId : NULL);
2051 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
2052 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2053 void *pvStructInfo, DWORD *pcbStructInfo)
2055 BOOL ret = FALSE;
2057 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2058 pvStructInfo, *pcbStructInfo);
2060 __TRY
2062 struct AsnDecodeSequenceItem items[] = {
2063 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
2064 CRYPT_AsnDecodeAttributeTypeValue,
2065 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
2066 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
2067 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
2068 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
2069 FALSE, TRUE,
2070 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
2073 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2074 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2075 pvStructInfo, pcbStructInfo, NULL);
2077 __EXCEPT_PAGE_FAULT
2079 SetLastError(STATUS_ACCESS_VIOLATION);
2081 __ENDTRY
2082 TRACE("returning %d\n", ret);
2083 return ret;
2086 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
2087 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2088 void *pvStructInfo, DWORD *pcbStructInfo)
2090 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2091 pvStructInfo, *pcbStructInfo);
2092 return FALSE;
2095 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
2096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2097 void *pvStructInfo, DWORD *pcbStructInfo)
2099 BOOL ret;
2100 DWORD bytesNeeded, dataLen;
2102 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2104 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2106 bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
2107 if (!pvStructInfo)
2108 *pcbStructInfo = bytesNeeded;
2109 else if (*pcbStructInfo < bytesNeeded)
2111 *pcbStructInfo = bytesNeeded;
2112 SetLastError(ERROR_MORE_DATA);
2113 ret = FALSE;
2115 else
2117 LPWSTR str;
2118 DWORD i;
2120 *pcbStructInfo = bytesNeeded;
2121 assert(pvStructInfo);
2122 str = *(LPWSTR *)pvStructInfo;
2123 for (i = 0; i < dataLen / 2; i++)
2124 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2125 pbEncoded[1 + lenBytes + 2 * i + 1];
2126 /* Decoded string is always NULL-terminated */
2127 str[i] = '\0';
2130 return ret;
2133 static BOOL CRYPT_AsnDecodeInteger(const BYTE *pbEncoded,
2134 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo)
2136 BOOL ret;
2137 DWORD bytesNeeded, dataLen;
2139 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2141 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2143 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2144 if (!pvStructInfo)
2145 *pcbStructInfo = bytesNeeded;
2146 else if (*pcbStructInfo < bytesNeeded)
2148 *pcbStructInfo = bytesNeeded;
2149 SetLastError(ERROR_MORE_DATA);
2150 ret = FALSE;
2152 else
2154 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2156 *pcbStructInfo = bytesNeeded;
2157 blob->cbData = dataLen;
2158 assert(blob->pbData);
2159 if (blob->cbData)
2161 DWORD i;
2163 for (i = 0; i < blob->cbData; i++)
2165 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2166 dataLen - i - 1);
2171 return ret;
2174 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2175 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2176 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2177 void *pvStructInfo, DWORD *pcbStructInfo)
2179 BOOL ret;
2180 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2181 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2182 DWORD size = sizeof(buf);
2184 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2185 ret = CRYPT_AsnDecodeInteger(pbEncoded, cbEncoded, 0, buf, &size);
2186 if (ret)
2188 if (!pvStructInfo)
2189 *pcbStructInfo = sizeof(int);
2190 else if (*pcbStructInfo < sizeof(int))
2192 *pcbStructInfo = sizeof(int);
2193 SetLastError(ERROR_MORE_DATA);
2194 ret = FALSE;
2196 else
2198 int val, i;
2200 *pcbStructInfo = sizeof(int);
2201 if (blob->pbData[blob->cbData - 1] & 0x80)
2203 /* initialize to a negative value to sign-extend */
2204 val = -1;
2206 else
2207 val = 0;
2208 for (i = 0; i < blob->cbData; i++)
2210 val <<= 8;
2211 val |= blob->pbData[blob->cbData - i - 1];
2213 memcpy(pvStructInfo, &val, sizeof(int));
2216 else if (GetLastError() == ERROR_MORE_DATA)
2217 SetLastError(CRYPT_E_ASN1_LARGE);
2218 return ret;
2221 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
2222 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2223 void *pvStructInfo, DWORD *pcbStructInfo)
2225 BOOL ret = FALSE;
2227 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2228 pvStructInfo, *pcbStructInfo);
2230 __TRY
2232 struct AsnDecodeSequenceItem items[] = {
2233 { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
2234 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2235 offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
2236 { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
2237 CRYPT_AsnDecodeInt, sizeof(DWORD),
2238 FALSE, FALSE, 0, 0 },
2241 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2242 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2243 pvStructInfo, pcbStructInfo, NULL);
2245 __EXCEPT_PAGE_FAULT
2247 SetLastError(STATUS_ACCESS_VIOLATION);
2249 __ENDTRY
2250 TRACE("returning %d\n", ret);
2251 return ret;
2254 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
2255 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2256 void *pvStructInfo, DWORD *pcbStructInfo)
2258 BOOL ret = FALSE;
2260 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2261 pvStructInfo, *pcbStructInfo);
2263 __TRY
2265 struct AsnDecodeSequenceItem items[] = {
2266 { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
2267 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2268 offsetof(CAT_NAMEVALUE, pwszTag), 0 },
2269 { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
2270 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2271 { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
2272 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2273 offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
2276 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2277 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2278 pvStructInfo, pcbStructInfo, NULL);
2280 __EXCEPT_PAGE_FAULT
2282 SetLastError(STATUS_ACCESS_VIOLATION);
2284 __ENDTRY
2285 TRACE("returning %d\n", ret);
2286 return ret;
2289 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2290 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2291 void *pvStructInfo, DWORD *pcbStructInfo)
2293 BOOL ret;
2295 if (cbEncoded < 3)
2297 SetLastError(CRYPT_E_ASN1_CORRUPT);
2298 return FALSE;
2300 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2302 SetLastError(CRYPT_E_ASN1_CORRUPT);
2303 return FALSE;
2305 if (pbEncoded[1] > 1)
2307 SetLastError(CRYPT_E_ASN1_CORRUPT);
2308 return FALSE;
2310 if (!pvStructInfo)
2312 *pcbStructInfo = sizeof(BOOL);
2313 ret = TRUE;
2315 else if (*pcbStructInfo < sizeof(BOOL))
2317 *pcbStructInfo = sizeof(BOOL);
2318 SetLastError(ERROR_MORE_DATA);
2319 ret = FALSE;
2321 else
2323 *pcbStructInfo = sizeof(BOOL);
2324 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2325 ret = TRUE;
2327 TRACE("returning %d (%08x)\n", ret, GetLastError());
2328 return ret;
2331 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType,
2332 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2333 void *pvStructInfo, DWORD *pcbStructInfo)
2335 BOOL ret = FALSE;
2337 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2338 pvStructInfo, *pcbStructInfo);
2340 __TRY
2342 struct AsnDecodeSequenceItem items[] = {
2343 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable),
2344 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2345 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria),
2346 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2349 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2350 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2351 pvStructInfo, pcbStructInfo, NULL);
2353 __EXCEPT_PAGE_FAULT
2355 SetLastError(STATUS_ACCESS_VIOLATION);
2357 __ENDTRY
2358 TRACE("returning %d\n", ret);
2359 return ret;