stash
[wine/wine64.git] / dlls / wintrust / asn.c
blobd3ac3e97a114a035c67c5644ba6e5ffa642a459d
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 if (*ptr == '.')
545 ptr++;
546 firstPos++;
548 while (ret && *ptr)
550 int pos;
552 /* note I assume each component is at most 32-bits long in base 2 */
553 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
555 if (val1 >= 0x10000000)
556 bytesNeeded += 5;
557 else if (val1 >= 0x200000)
558 bytesNeeded += 4;
559 else if (val1 >= 0x4000)
560 bytesNeeded += 3;
561 else if (val1 >= 0x80)
562 bytesNeeded += 2;
563 else
564 bytesNeeded += 1;
565 ptr += pos;
566 if (*ptr == '.')
567 ptr++;
569 else
571 SetLastError(CRYPT_E_ASN1_ERROR);
572 return FALSE;
575 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
577 else
578 lenBytes = 1;
579 bytesNeeded += 1 + lenBytes;
580 if (pbEncoded)
582 if (*pcbEncoded < bytesNeeded)
584 SetLastError(ERROR_MORE_DATA);
585 ret = FALSE;
587 else
589 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
590 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
591 pbEncoded += lenBytes;
592 if (pszObjId)
594 const char *ptr;
595 int val, pos;
597 *pbEncoded++ = firstByte;
598 ptr = pszObjId + firstPos;
599 while (ret && *ptr)
601 sscanf(ptr, "%d%n", &val, &pos);
603 unsigned char outBytes[5];
604 int numBytes, i;
606 if (val >= 0x10000000)
607 numBytes = 5;
608 else if (val >= 0x200000)
609 numBytes = 4;
610 else if (val >= 0x4000)
611 numBytes = 3;
612 else if (val >= 0x80)
613 numBytes = 2;
614 else
615 numBytes = 1;
616 for (i = numBytes; i > 0; i--)
618 outBytes[i - 1] = val & 0x7f;
619 val >>= 7;
621 for (i = 0; i < numBytes - 1; i++)
622 *pbEncoded++ = outBytes[i] | 0x80;
623 *pbEncoded++ = outBytes[i];
624 ptr += pos;
625 if (*ptr == '.')
626 ptr++;
632 *pcbEncoded = bytesNeeded;
633 return ret;
636 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
637 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
638 DWORD *pcbEncoded)
640 const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
641 BOOL ret = TRUE;
643 if (!pbEncoded)
644 *pcbEncoded = blob->cbData;
645 else if (*pcbEncoded < blob->cbData)
647 *pcbEncoded = blob->cbData;
648 SetLastError(ERROR_MORE_DATA);
649 ret = FALSE;
651 else
653 if (blob->cbData)
654 memcpy(pbEncoded, blob->pbData, blob->cbData);
655 *pcbEncoded = blob->cbData;
657 return ret;
660 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
661 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
662 BYTE *pbEncoded, DWORD *pcbEncoded)
664 const CRYPT_ALGORITHM_IDENTIFIER *algo =
665 (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
666 static const BYTE asn1Null[] = { ASN_NULL, 0 };
667 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
668 (LPBYTE)asn1Null };
669 BOOL ret;
670 struct AsnEncodeSequenceItem items[2] = {
671 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
672 { NULL, CRYPT_CopyEncodedBlob, 0 },
675 if (algo->Parameters.cbData)
676 items[1].pvStructInfo = &algo->Parameters;
677 else
678 items[1].pvStructInfo = &nullBlob;
679 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
680 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
681 return ret;
684 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
685 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
686 DWORD *pcbEncoded)
688 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
689 (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
690 struct AsnEncodeSequenceItem items[] = {
691 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
692 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
695 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
696 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
699 struct SPCDigest
701 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
702 CRYPT_HASH_BLOB Digest;
705 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
706 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
707 DWORD *pcbEncoded)
709 const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
710 struct AsnEncodeSequenceItem items[] = {
711 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
712 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 },
715 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
716 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
719 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
720 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
721 DWORD *pcbEncoded)
723 BOOL ret = FALSE;
725 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
726 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
728 __TRY
730 const SPC_INDIRECT_DATA_CONTENT *data =
731 (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
732 struct AsnEncodeSequenceItem items[] = {
733 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
734 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
737 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
738 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
740 __EXCEPT_PAGE_FAULT
742 SetLastError(STATUS_ACCESS_VIOLATION);
744 __ENDTRY
745 return ret;
748 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
749 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
750 DWORD *pcbEncoded)
752 BOOL ret = TRUE;
753 LPCWSTR str = (LPCWSTR)pvStructInfo;
754 DWORD bytesNeeded, lenBytes, strLen;
756 if (str)
757 strLen = lstrlenW(str);
758 else
759 strLen = 0;
760 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
761 bytesNeeded = 1 + lenBytes + strLen * 2;
762 if (!pbEncoded)
763 *pcbEncoded = bytesNeeded;
764 else if (*pcbEncoded < bytesNeeded)
766 *pcbEncoded = bytesNeeded;
767 SetLastError(ERROR_MORE_DATA);
768 ret = FALSE;
770 else
772 DWORD i;
774 *pcbEncoded = bytesNeeded;
775 *pbEncoded++ = ASN_BMPSTRING;
776 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
777 pbEncoded += lenBytes;
778 for (i = 0; i < strLen; i++)
780 *pbEncoded++ = (str[i] & 0xff00) >> 8;
781 *pbEncoded++ = str[i] & 0x00ff;
784 return ret;
787 struct AsnEncodeTagSwappedItem
789 BYTE tag;
790 const void *pvStructInfo;
791 CryptEncodeObjectFunc encodeFunc;
794 /* Sort of a wacky hack, it encodes something using the struct
795 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
796 * given in the struct AsnEncodeTagSwappedItem.
798 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
799 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
800 DWORD *pcbEncoded)
802 BOOL ret;
803 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
805 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
806 item->pvStructInfo, pbEncoded, pcbEncoded);
807 if (ret && pbEncoded)
808 *pbEncoded = item->tag;
809 return ret;
812 BOOL WINAPI WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType,
813 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
814 DWORD *pcbEncoded)
816 BOOL ret = FALSE;
818 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
819 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
821 __TRY
823 const SPC_SP_OPUS_INFO *info = pvStructInfo;
825 if (info->pMoreInfo &&
826 info->pMoreInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
827 info->pMoreInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
828 info->pMoreInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
829 SetLastError(E_INVALIDARG);
830 else if (info->pPublisherInfo &&
831 info->pPublisherInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
832 info->pPublisherInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
833 info->pPublisherInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
834 SetLastError(E_INVALIDARG);
835 else
837 struct AsnEncodeSequenceItem items[3] = { { 0 } };
838 struct AsnConstructedItem constructed[3] = { { 0 } };
839 struct AsnEncodeTagSwappedItem swapped;
840 DWORD cItem = 0, cConstructed = 0;
842 if (info->pwszProgramName)
844 swapped.tag = ASN_CONTEXT;
845 swapped.pvStructInfo = info->pwszProgramName;
846 swapped.encodeFunc = CRYPT_AsnEncodeBMPString;
847 constructed[cConstructed].tag = 0;
848 constructed[cConstructed].pvStructInfo = &swapped;
849 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeSwapTag;
850 items[cItem].pvStructInfo = &constructed[cConstructed];
851 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
852 cConstructed++;
853 cItem++;
855 if (info->pMoreInfo)
857 constructed[cConstructed].tag = 1;
858 constructed[cConstructed].pvStructInfo = info->pMoreInfo;
859 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
860 items[cItem].pvStructInfo = &constructed[cConstructed];
861 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
862 cConstructed++;
863 cItem++;
865 if (info->pPublisherInfo)
867 constructed[cConstructed].tag = 2;
868 constructed[cConstructed].pvStructInfo = info->pPublisherInfo;
869 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
870 items[cItem].pvStructInfo = &constructed[cConstructed];
871 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
872 cConstructed++;
873 cItem++;
875 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
876 items, cItem, pbEncoded, pcbEncoded);
879 __EXCEPT_PAGE_FAULT
881 SetLastError(STATUS_ACCESS_VIOLATION);
883 __ENDTRY
884 return ret;
887 static BOOL CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
888 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
889 DWORD *pcbEncoded)
891 BOOL ret;
893 __TRY
895 DWORD significantBytes, lenBytes, bytesNeeded;
896 BYTE padByte = 0;
897 BOOL pad = FALSE;
898 const CRYPT_INTEGER_BLOB *blob =
899 (const CRYPT_INTEGER_BLOB *)pvStructInfo;
901 significantBytes = blob->cbData;
902 if (significantBytes)
904 if (blob->pbData[significantBytes - 1] & 0x80)
906 /* negative, lop off leading (little-endian) 0xffs */
907 for (; significantBytes > 0 &&
908 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
910 if (blob->pbData[significantBytes - 1] < 0x80)
912 padByte = 0xff;
913 pad = TRUE;
916 else
918 /* positive, lop off leading (little-endian) zeroes */
919 for (; significantBytes > 0 &&
920 !blob->pbData[significantBytes - 1]; significantBytes--)
922 if (significantBytes == 0)
923 significantBytes = 1;
924 if (blob->pbData[significantBytes - 1] > 0x7f)
926 padByte = 0;
927 pad = TRUE;
931 if (pad)
932 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
933 else
934 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
935 bytesNeeded = 1 + lenBytes + significantBytes;
936 if (pad)
937 bytesNeeded++;
938 if (!pbEncoded)
940 *pcbEncoded = bytesNeeded;
941 ret = TRUE;
943 else if (*pcbEncoded < bytesNeeded)
945 *pcbEncoded = bytesNeeded;
946 SetLastError(ERROR_MORE_DATA);
947 ret = FALSE;
949 else
951 *pcbEncoded = bytesNeeded;
952 *pbEncoded++ = ASN_INTEGER;
953 if (pad)
955 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
956 pbEncoded += lenBytes;
957 *pbEncoded++ = padByte;
959 else
961 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
962 pbEncoded += lenBytes;
964 for (; significantBytes > 0; significantBytes--)
965 *(pbEncoded++) = blob->pbData[significantBytes - 1];
966 ret = TRUE;
969 __EXCEPT_PAGE_FAULT
971 SetLastError(STATUS_ACCESS_VIOLATION);
972 ret = FALSE;
974 __ENDTRY
975 return ret;
978 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
979 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
980 DWORD *pcbEncoded)
982 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
984 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
985 &blob, pbEncoded, pcbEncoded);
988 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
989 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
990 DWORD *pcbEncoded)
992 BOOL ret = FALSE;
994 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
995 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
997 __TRY
999 const CAT_MEMBERINFO *info = (const CAT_MEMBERINFO *)pvStructInfo;
1000 struct AsnEncodeSequenceItem items[] = {
1001 { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
1002 { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
1005 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1006 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1008 __EXCEPT_PAGE_FAULT
1010 SetLastError(STATUS_ACCESS_VIOLATION);
1012 __ENDTRY
1013 return ret;
1016 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
1017 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1018 DWORD *pcbEncoded)
1020 BOOL ret = FALSE;
1022 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
1023 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1025 __TRY
1027 const CAT_NAMEVALUE *value = (const CAT_NAMEVALUE *)pvStructInfo;
1028 struct AsnEncodeSequenceItem items[] = {
1029 { value->pwszTag, CRYPT_AsnEncodeBMPString, 0 },
1030 { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
1031 { &value->Value, CRYPT_AsnEncodeOctets, 0 },
1034 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1035 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1037 __EXCEPT_PAGE_FAULT
1039 SetLastError(STATUS_ACCESS_VIOLATION);
1041 __ENDTRY
1042 return ret;
1045 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1046 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1047 DWORD *pcbEncoded)
1049 BOOL val = *(const BOOL *)pvStructInfo, ret;
1051 TRACE("%d\n", val);
1053 if (!pbEncoded)
1055 *pcbEncoded = 3;
1056 ret = TRUE;
1058 else if (*pcbEncoded < 3)
1060 *pcbEncoded = 3;
1061 SetLastError(ERROR_MORE_DATA);
1062 ret = FALSE;
1064 else
1066 *pcbEncoded = 3;
1067 *pbEncoded++ = ASN_BOOL;
1068 *pbEncoded++ = 1;
1069 *pbEncoded++ = val ? 0xff : 0;
1070 ret = TRUE;
1072 TRACE("returning %d (%08x)\n", ret, GetLastError());
1073 return ret;
1076 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType,
1077 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1078 DWORD *pcbEncoded)
1080 BOOL ret = FALSE;
1082 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
1083 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1085 __TRY
1087 const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo;
1088 struct AsnEncodeSequenceItem items[] = {
1089 { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 },
1090 { &criteria->fMeetsCriteria, CRYPT_AsnEncodeBool, 0 },
1093 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1094 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1096 __EXCEPT_PAGE_FAULT
1098 SetLastError(STATUS_ACCESS_VIOLATION);
1100 __ENDTRY
1101 return ret;
1104 /* Gets the number of length bytes from the given (leading) length byte */
1105 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1107 /* Helper function to get the encoded length of the data starting at pbEncoded,
1108 * where pbEncoded[0] is the tag. If the data are too short to contain a
1109 * length or if the length is too large for cbEncoded, sets an appropriate
1110 * error code and returns FALSE.
1112 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
1114 BOOL ret;
1116 if (cbEncoded <= 1)
1118 SetLastError(CRYPT_E_ASN1_CORRUPT);
1119 ret = FALSE;
1121 else if (pbEncoded[1] <= 0x7f)
1123 if (pbEncoded[1] + 1 > cbEncoded)
1125 SetLastError(CRYPT_E_ASN1_EOD);
1126 ret = FALSE;
1128 else
1130 *len = pbEncoded[1];
1131 ret = TRUE;
1134 else if (pbEncoded[1] == 0x80)
1136 FIXME("unimplemented for indefinite-length encoding\n");
1137 SetLastError(CRYPT_E_ASN1_CORRUPT);
1138 ret = FALSE;
1140 else
1142 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
1144 if (lenLen > sizeof(DWORD) + 1)
1146 SetLastError(CRYPT_E_ASN1_LARGE);
1147 ret = FALSE;
1149 else if (lenLen + 2 > cbEncoded)
1151 SetLastError(CRYPT_E_ASN1_CORRUPT);
1152 ret = FALSE;
1154 else
1156 DWORD out = 0;
1158 pbEncoded += 2;
1159 while (--lenLen)
1161 out <<= 8;
1162 out |= *pbEncoded++;
1164 if (out + lenLen + 1 > cbEncoded)
1166 SetLastError(CRYPT_E_ASN1_EOD);
1167 ret = FALSE;
1169 else
1171 *len = out;
1172 ret = TRUE;
1176 return ret;
1179 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1180 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1181 void *pvStructInfo, DWORD *pcbStructInfo)
1183 BOOL ret;
1184 DWORD bytesNeeded, dataLen;
1186 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1187 pvStructInfo, *pcbStructInfo);
1189 if (!cbEncoded)
1191 SetLastError(CRYPT_E_ASN1_CORRUPT);
1192 ret = FALSE;
1194 else if (pbEncoded[0] != ASN_OCTETSTRING)
1196 SetLastError(CRYPT_E_ASN1_BADTAG);
1197 ret = FALSE;
1199 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1201 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1202 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1203 else
1204 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1205 if (!pvStructInfo)
1206 *pcbStructInfo = bytesNeeded;
1207 else if (*pcbStructInfo < bytesNeeded)
1209 SetLastError(ERROR_MORE_DATA);
1210 *pcbStructInfo = bytesNeeded;
1211 ret = FALSE;
1213 else
1215 CRYPT_DATA_BLOB *blob;
1216 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1218 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1219 blob->cbData = dataLen;
1220 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1221 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1222 else
1224 assert(blob->pbData);
1225 if (blob->cbData)
1226 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1227 blob->cbData);
1231 return ret;
1234 static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
1235 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1236 void *pvStructInfo, DWORD *pcbStructInfo)
1238 BOOL ret = FALSE;
1239 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
1241 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1242 pvStructInfo, *pcbStructInfo);
1244 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1246 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1247 DWORD realDataLen;
1249 switch (pbEncoded[0])
1251 case ASN_CONTEXT:
1252 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1253 if (!pvStructInfo)
1254 *pcbStructInfo = bytesNeeded;
1255 else if (*pcbStructInfo < bytesNeeded)
1257 *pcbStructInfo = bytesNeeded;
1258 SetLastError(ERROR_MORE_DATA);
1259 ret = FALSE;
1261 else
1263 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1264 DWORD i;
1266 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
1267 for (i = 0; i < dataLen; i++)
1268 link->u.pwszUrl[i] =
1269 *(pbEncoded + 1 + lenBytes + i);
1270 link->u.pwszUrl[i] = '\0';
1271 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
1273 break;
1274 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
1276 CRYPT_DATA_BLOB classId;
1277 DWORD size = sizeof(classId);
1279 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1280 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
1281 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
1283 if (classId.cbData != sizeof(SPC_UUID))
1285 SetLastError(CRYPT_E_BAD_ENCODE);
1286 ret = FALSE;
1288 else
1290 CRYPT_DATA_BLOB data;
1292 /* The tag length for the classId must be 1 since the
1293 * length is correct.
1295 size = sizeof(data);
1296 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1297 pbEncoded + 3 + lenBytes + classId.cbData,
1298 cbEncoded - 3 - lenBytes - classId.cbData,
1299 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
1301 bytesNeeded += data.cbData;
1302 if (!pvStructInfo)
1303 *pcbStructInfo = bytesNeeded;
1304 else if (*pcbStructInfo < bytesNeeded)
1306 *pcbStructInfo = bytesNeeded;
1307 SetLastError(ERROR_MORE_DATA);
1308 ret = FALSE;
1310 else
1312 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1314 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
1315 /* pwszFile pointer was set by caller, copy it
1316 * before overwriting it
1318 link->u.Moniker.SerializedData.pbData =
1319 (BYTE *)link->u.pwszFile;
1320 memcpy(link->u.Moniker.ClassId, classId.pbData,
1321 classId.cbData);
1322 memcpy(link->u.Moniker.SerializedData.pbData,
1323 data.pbData, data.cbData);
1324 link->u.Moniker.SerializedData.cbData = data.cbData;
1329 break;
1331 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
1332 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
1333 SetLastError(CRYPT_E_ASN1_BADTAG);
1334 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
1335 &realDataLen)))
1337 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
1339 bytesNeeded += realDataLen + sizeof(WCHAR);
1340 if (!pvStructInfo)
1341 *pcbStructInfo = bytesNeeded;
1342 else if (*pcbStructInfo < bytesNeeded)
1344 *pcbStructInfo = bytesNeeded;
1345 SetLastError(ERROR_MORE_DATA);
1346 ret = FALSE;
1348 else
1350 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1351 DWORD i;
1352 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
1354 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1355 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
1356 link->u.pwszFile[i] =
1357 hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
1358 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
1359 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
1362 else
1364 bytesNeeded += sizeof(WCHAR);
1365 if (!pvStructInfo)
1366 *pcbStructInfo = bytesNeeded;
1367 else if (*pcbStructInfo < bytesNeeded)
1369 *pcbStructInfo = bytesNeeded;
1370 SetLastError(ERROR_MORE_DATA);
1371 ret = FALSE;
1373 else
1375 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1377 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1378 link->u.pwszFile[0] = '\0';
1379 ret = TRUE;
1382 break;
1383 default:
1384 SetLastError(CRYPT_E_ASN1_BADTAG);
1387 TRACE("returning %d\n", ret);
1388 return ret;
1391 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1392 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1393 void *pvStructInfo, DWORD *pcbStructInfo)
1395 BOOL ret = FALSE;
1397 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1398 pvStructInfo, *pcbStructInfo);
1400 __TRY
1402 DWORD bytesNeeded;
1404 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1405 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1406 if (ret)
1408 if (!pvStructInfo)
1409 *pcbStructInfo = bytesNeeded;
1410 else if (*pcbStructInfo < bytesNeeded)
1412 *pcbStructInfo = bytesNeeded;
1413 SetLastError(ERROR_MORE_DATA);
1414 ret = FALSE;
1416 else
1418 SPC_LINK *link = (SPC_LINK *)pvStructInfo;
1420 link->u.pwszFile =
1421 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1422 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1423 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1424 pcbStructInfo);
1428 __EXCEPT_PAGE_FAULT
1430 SetLastError(STATUS_ACCESS_VIOLATION);
1432 __ENDTRY
1433 TRACE("returning %d\n", ret);
1434 return ret;
1437 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1438 DWORD, DWORD, void *, DWORD *);
1440 /* tag:
1441 * The expected tag of the item. If tag is 0, decodeFunc is called
1442 * regardless of the tag value seen.
1443 * offset:
1444 * A sequence is decoded into a struct. The offset member is the
1445 * offset of this item within that struct.
1446 * decodeFunc:
1447 * The decoder function to use. If this is NULL, then the member isn't
1448 * decoded, but minSize space is reserved for it.
1449 * minSize:
1450 * The minimum amount of space occupied after decoding. You must set this.
1451 * optional:
1452 * If true, and the tag doesn't match the expected tag for this item,
1453 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1454 * filled with 0 for this member.
1455 * hasPointer, pointerOffset:
1456 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1457 * the offset within the struct of the data pointer (or to the
1458 * first data pointer, if more than one exist).
1459 * size:
1460 * Used by CRYPT_AsnDecodeSequence, not for your use.
1462 struct AsnDecodeSequenceItem
1464 BYTE tag;
1465 DWORD offset;
1466 CryptDecodeObjectFunc decodeFunc;
1467 DWORD minSize;
1468 BOOL optional;
1469 BOOL hasPointer;
1470 DWORD pointerOffset;
1471 DWORD size;
1474 /* Decodes the items in a sequence, where the items are described in items,
1475 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1476 * pvStructInfo. nextData is a pointer to the memory location at which the
1477 * first decoded item with a dynamic pointer should point.
1478 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1480 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1481 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1482 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1483 DWORD *cbDecoded)
1485 BOOL ret;
1486 DWORD i, decoded = 0;
1487 const BYTE *ptr = pbEncoded;
1489 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1490 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1492 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1494 if (cbEncoded - (ptr - pbEncoded) != 0)
1496 DWORD nextItemLen;
1498 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1499 &nextItemLen)))
1501 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1503 if (ptr[0] == items[i].tag || !items[i].tag)
1505 if (nextData && pvStructInfo && items[i].hasPointer)
1507 TRACE("Setting next pointer to %p\n",
1508 nextData);
1509 *(BYTE **)((BYTE *)pvStructInfo +
1510 items[i].pointerOffset) = nextData;
1512 if (items[i].decodeFunc)
1514 if (pvStructInfo)
1515 TRACE("decoding item %d\n", i);
1516 else
1517 TRACE("sizing item %d\n", i);
1518 ret = items[i].decodeFunc(dwCertEncodingType,
1519 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1520 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1521 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1522 : NULL, &items[i].size);
1523 if (ret)
1525 /* Account for alignment padding */
1526 if (items[i].size % sizeof(DWORD))
1527 items[i].size += sizeof(DWORD) -
1528 items[i].size % sizeof(DWORD);
1529 TRACE("item %d size: %d\n", i, items[i].size);
1530 if (nextData && items[i].hasPointer &&
1531 items[i].size > items[i].minSize)
1532 nextData += items[i].size - items[i].minSize;
1533 ptr += 1 + nextItemLenBytes + nextItemLen;
1534 decoded += 1 + nextItemLenBytes + nextItemLen;
1535 TRACE("item %d: decoded %d bytes\n", i,
1536 1 + nextItemLenBytes + nextItemLen);
1538 else if (items[i].optional &&
1539 GetLastError() == CRYPT_E_ASN1_BADTAG)
1541 TRACE("skipping optional item %d\n", i);
1542 items[i].size = items[i].minSize;
1543 SetLastError(NOERROR);
1544 ret = TRUE;
1546 else
1547 TRACE("item %d failed: %08x\n", i,
1548 GetLastError());
1550 else
1552 TRACE("item %d: decoded %d bytes\n", i,
1553 1 + nextItemLenBytes + nextItemLen);
1554 ptr += 1 + nextItemLenBytes + nextItemLen;
1555 decoded += 1 + nextItemLenBytes + nextItemLen;
1556 items[i].size = items[i].minSize;
1559 else if (items[i].optional)
1561 TRACE("skipping optional item %d\n", i);
1562 items[i].size = items[i].minSize;
1564 else
1566 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1567 i, ptr[0], items[i].tag);
1568 SetLastError(CRYPT_E_ASN1_BADTAG);
1569 ret = FALSE;
1573 else if (items[i].optional)
1575 TRACE("missing optional item %d, skipping\n", i);
1576 items[i].size = items[i].minSize;
1578 else
1580 TRACE("not enough bytes for item %d, failing\n", i);
1581 SetLastError(CRYPT_E_ASN1_CORRUPT);
1582 ret = FALSE;
1585 if (ret)
1586 *cbDecoded = decoded;
1587 TRACE("returning %d\n", ret);
1588 return ret;
1591 /* This decodes an arbitrary sequence into a contiguous block of memory
1592 * (basically, a struct.) Each element being decoded is described by a struct
1593 * AsnDecodeSequenceItem, see above.
1594 * startingPointer is an optional pointer to the first place where dynamic
1595 * data will be stored. If you know the starting offset, you may pass it
1596 * here. Otherwise, pass NULL, and one will be inferred from the items.
1598 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1599 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1600 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1601 void *startingPointer)
1603 BOOL ret;
1605 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
1606 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1608 if (pbEncoded[0] == ASN_SEQUENCE)
1610 DWORD dataLen;
1612 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1614 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1615 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1617 cbEncoded -= 1 + lenBytes;
1618 if (cbEncoded < dataLen)
1620 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
1621 cbEncoded);
1622 SetLastError(CRYPT_E_ASN1_CORRUPT);
1623 ret = FALSE;
1625 else
1626 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1627 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1628 if (ret && cbDecoded != dataLen)
1630 TRACE("expected %d decoded, got %d, failing\n", dataLen,
1631 cbDecoded);
1632 SetLastError(CRYPT_E_ASN1_CORRUPT);
1633 ret = FALSE;
1635 if (ret)
1637 DWORD i, bytesNeeded = 0, structSize = 0;
1639 for (i = 0; i < cItem; i++)
1641 bytesNeeded += items[i].size;
1642 structSize += items[i].minSize;
1644 if (!pvStructInfo)
1645 *pcbStructInfo = bytesNeeded;
1646 else if (*pcbStructInfo < bytesNeeded)
1648 SetLastError(ERROR_MORE_DATA);
1649 *pcbStructInfo = bytesNeeded;
1650 ret = FALSE;
1652 else
1654 BYTE *nextData;
1656 *pcbStructInfo = bytesNeeded;
1657 if (startingPointer)
1658 nextData = (BYTE *)startingPointer;
1659 else
1660 nextData = (BYTE *)pvStructInfo + structSize;
1661 memset(pvStructInfo, 0, structSize);
1662 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1663 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1664 &cbDecoded);
1669 else
1671 SetLastError(CRYPT_E_ASN1_BADTAG);
1672 ret = FALSE;
1674 TRACE("returning %d (%08x)\n", ret, GetLastError());
1675 return ret;
1678 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1679 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1680 void *pvStructInfo, DWORD *pcbStructInfo)
1682 BOOL ret;
1684 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
1685 pvStructInfo, *pcbStructInfo);
1687 if (pbEncoded[0] == ASN_BITSTRING)
1689 DWORD bytesNeeded, dataLen;
1691 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1693 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1694 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1695 else
1696 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1697 if (!pvStructInfo)
1698 *pcbStructInfo = bytesNeeded;
1699 else if (*pcbStructInfo < bytesNeeded)
1701 *pcbStructInfo = bytesNeeded;
1702 SetLastError(ERROR_MORE_DATA);
1703 ret = FALSE;
1705 else
1707 CRYPT_BIT_BLOB *blob;
1709 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
1710 blob->cbData = dataLen - 1;
1711 blob->cUnusedBits = *(pbEncoded + 1 +
1712 GET_LEN_BYTES(pbEncoded[1]));
1713 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1715 blob->pbData = (BYTE *)pbEncoded + 2 +
1716 GET_LEN_BYTES(pbEncoded[1]);
1718 else
1720 assert(blob->pbData);
1721 if (blob->cbData)
1723 BYTE mask = 0xff << blob->cUnusedBits;
1725 memcpy(blob->pbData, pbEncoded + 2 +
1726 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1727 blob->pbData[blob->cbData - 1] &= mask;
1733 else
1735 SetLastError(CRYPT_E_ASN1_BADTAG);
1736 ret = FALSE;
1738 TRACE("returning %d (%08x)\n", ret, GetLastError());
1739 return ret;
1742 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1743 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1744 void *pvStructInfo, DWORD *pcbStructInfo)
1746 BOOL ret = FALSE;
1747 DWORD dataLen;
1749 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1751 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1752 DWORD size;
1753 SPC_LINK **pLink = (SPC_LINK **)pvStructInfo;
1755 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1756 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1757 if (ret)
1759 if (!pvStructInfo)
1760 *pcbStructInfo = size + sizeof(PSPC_LINK);
1761 else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1763 *pcbStructInfo = size + sizeof(PSPC_LINK);
1764 SetLastError(ERROR_MORE_DATA);
1765 ret = FALSE;
1767 else
1769 *pcbStructInfo = size + sizeof(PSPC_LINK);
1770 /* Set imageData's pointer if necessary */
1771 if (size > sizeof(SPC_LINK))
1773 (*pLink)->u.pwszUrl =
1774 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1776 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1777 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1778 *pLink, pcbStructInfo);
1782 return ret;
1785 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1786 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1787 void *pvStructInfo, DWORD *pcbStructInfo)
1789 BOOL ret = FALSE;
1791 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1792 pvStructInfo, *pcbStructInfo);
1794 __TRY
1796 struct AsnDecodeSequenceItem items[] = {
1797 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1798 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1799 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1800 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1801 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1802 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1805 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1806 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1807 pvStructInfo, pcbStructInfo, NULL);
1809 __EXCEPT_PAGE_FAULT
1811 SetLastError(STATUS_ACCESS_VIOLATION);
1813 __ENDTRY
1814 TRACE("returning %d\n", ret);
1815 return ret;
1818 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1820 void *pvStructInfo, DWORD *pcbStructInfo)
1822 BOOL ret = TRUE;
1823 DWORD dataLen;
1825 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1826 pvStructInfo, *pcbStructInfo);
1828 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1830 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1831 DWORD bytesNeeded = sizeof(LPSTR);
1833 if (dataLen)
1835 /* The largest possible string for the first two components
1836 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1838 char firstTwo[6];
1839 const BYTE *ptr;
1841 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1842 pbEncoded[1 + lenBytes] / 40,
1843 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1844 * 40);
1845 bytesNeeded += strlen(firstTwo) + 1;
1846 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1847 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1849 /* large enough for ".4000000" */
1850 char str[9];
1851 int val = 0;
1853 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1854 (*ptr & 0x80))
1856 val <<= 7;
1857 val |= *ptr & 0x7f;
1858 ptr++;
1860 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1861 (*ptr & 0x80))
1863 SetLastError(CRYPT_E_ASN1_CORRUPT);
1864 ret = FALSE;
1866 else
1868 val <<= 7;
1869 val |= *ptr++;
1870 snprintf(str, sizeof(str), ".%d", val);
1871 bytesNeeded += strlen(str);
1875 if (!pvStructInfo)
1876 *pcbStructInfo = bytesNeeded;
1877 else if (*pcbStructInfo < bytesNeeded)
1879 *pcbStructInfo = bytesNeeded;
1880 SetLastError(ERROR_MORE_DATA);
1881 ret = FALSE;
1883 else
1885 if (dataLen)
1887 const BYTE *ptr;
1888 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1890 *pszObjId = 0;
1891 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1892 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1893 40) * 40);
1894 pszObjId += strlen(pszObjId);
1895 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1896 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1898 int val = 0;
1900 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1901 (*ptr & 0x80))
1903 val <<= 7;
1904 val |= *ptr & 0x7f;
1905 ptr++;
1907 val <<= 7;
1908 val |= *ptr++;
1909 sprintf(pszObjId, ".%d", val);
1910 pszObjId += strlen(pszObjId);
1913 else
1914 *(LPSTR *)pvStructInfo = NULL;
1915 *pcbStructInfo = bytesNeeded;
1918 return ret;
1921 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1922 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1923 void *pvStructInfo, DWORD *pcbStructInfo)
1925 BOOL ret = FALSE;
1927 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1928 pvStructInfo, *pcbStructInfo);
1930 if (!cbEncoded)
1931 SetLastError(CRYPT_E_ASN1_CORRUPT);
1932 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1933 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1934 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1935 else
1936 SetLastError(CRYPT_E_ASN1_BADTAG);
1937 return ret;
1940 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1941 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1942 void *pvStructInfo, DWORD *pcbStructInfo)
1944 BOOL ret = TRUE;
1945 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1947 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1948 pvStructInfo, *pcbStructInfo);
1950 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1951 bytesNeeded += cbEncoded;
1952 if (!pvStructInfo)
1953 *pcbStructInfo = bytesNeeded;
1954 else if (*pcbStructInfo < bytesNeeded)
1956 SetLastError(ERROR_MORE_DATA);
1957 *pcbStructInfo = bytesNeeded;
1958 ret = FALSE;
1960 else
1962 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1964 *pcbStructInfo = bytesNeeded;
1965 blob->cbData = cbEncoded;
1966 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1967 blob->pbData = (LPBYTE)pbEncoded;
1968 else
1970 assert(blob->pbData);
1971 memcpy(blob->pbData, pbEncoded, blob->cbData);
1974 return ret;
1977 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1978 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1979 void *pvStructInfo, DWORD *pcbStructInfo)
1981 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
1982 (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
1983 struct AsnDecodeSequenceItem items[] = {
1984 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1985 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1986 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1987 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1988 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1989 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1992 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1993 pvStructInfo, *pcbStructInfo);
1995 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1996 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1997 pvStructInfo, pcbStructInfo,
1998 typeValue ? typeValue->pszObjId : NULL);
2001 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
2002 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2003 void *pvStructInfo, DWORD *pcbStructInfo)
2005 CRYPT_ALGORITHM_IDENTIFIER *algo =
2006 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2007 BOOL ret = TRUE;
2008 struct AsnDecodeSequenceItem items[] = {
2009 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2010 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2011 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2012 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2013 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2014 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2017 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2018 pvStructInfo, *pcbStructInfo);
2020 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2021 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2022 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
2023 if (ret && pvStructInfo)
2025 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2026 debugstr_a(algo->pszObjId));
2028 return ret;
2031 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
2032 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2033 void *pvStructInfo, DWORD *pcbStructInfo)
2035 struct SPCDigest *digest =
2036 (struct SPCDigest *)pvStructInfo;
2037 struct AsnDecodeSequenceItem items[] = {
2038 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
2039 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2040 FALSE, TRUE,
2041 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
2042 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
2043 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
2044 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
2047 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2048 pvStructInfo, *pcbStructInfo);
2050 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2051 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2052 pvStructInfo, pcbStructInfo,
2053 digest ? digest->DigestAlgorithm.pszObjId : NULL);
2056 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
2057 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2058 void *pvStructInfo, DWORD *pcbStructInfo)
2060 BOOL ret = FALSE;
2062 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2063 pvStructInfo, *pcbStructInfo);
2065 __TRY
2067 struct AsnDecodeSequenceItem items[] = {
2068 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
2069 CRYPT_AsnDecodeAttributeTypeValue,
2070 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
2071 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
2072 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
2073 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
2074 FALSE, TRUE,
2075 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
2078 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2079 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2080 pvStructInfo, pcbStructInfo, NULL);
2082 __EXCEPT_PAGE_FAULT
2084 SetLastError(STATUS_ACCESS_VIOLATION);
2086 __ENDTRY
2087 TRACE("returning %d\n", ret);
2088 return ret;
2091 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
2092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2093 void *pvStructInfo, DWORD *pcbStructInfo)
2095 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2096 pvStructInfo, *pcbStructInfo);
2097 return FALSE;
2100 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
2101 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2102 void *pvStructInfo, DWORD *pcbStructInfo)
2104 BOOL ret;
2105 DWORD bytesNeeded, dataLen;
2107 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2109 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2111 bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
2112 if (!pvStructInfo)
2113 *pcbStructInfo = bytesNeeded;
2114 else if (*pcbStructInfo < bytesNeeded)
2116 *pcbStructInfo = bytesNeeded;
2117 SetLastError(ERROR_MORE_DATA);
2118 ret = FALSE;
2120 else
2122 LPWSTR str;
2123 DWORD i;
2125 *pcbStructInfo = bytesNeeded;
2126 assert(pvStructInfo);
2127 str = *(LPWSTR *)pvStructInfo;
2128 for (i = 0; i < dataLen / 2; i++)
2129 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2130 pbEncoded[1 + lenBytes + 2 * i + 1];
2131 /* Decoded string is always NULL-terminated */
2132 str[i] = '\0';
2135 return ret;
2138 static BOOL CRYPT_AsnDecodeInteger(const BYTE *pbEncoded,
2139 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo)
2141 BOOL ret;
2142 DWORD bytesNeeded, dataLen;
2144 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2146 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2148 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2149 if (!pvStructInfo)
2150 *pcbStructInfo = bytesNeeded;
2151 else if (*pcbStructInfo < bytesNeeded)
2153 *pcbStructInfo = bytesNeeded;
2154 SetLastError(ERROR_MORE_DATA);
2155 ret = FALSE;
2157 else
2159 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2161 *pcbStructInfo = bytesNeeded;
2162 blob->cbData = dataLen;
2163 assert(blob->pbData);
2164 if (blob->cbData)
2166 DWORD i;
2168 for (i = 0; i < blob->cbData; i++)
2170 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2171 dataLen - i - 1);
2176 return ret;
2179 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2180 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2181 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2182 void *pvStructInfo, DWORD *pcbStructInfo)
2184 BOOL ret;
2185 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2186 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2187 DWORD size = sizeof(buf);
2189 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2190 ret = CRYPT_AsnDecodeInteger(pbEncoded, cbEncoded, 0, buf, &size);
2191 if (ret)
2193 if (!pvStructInfo)
2194 *pcbStructInfo = sizeof(int);
2195 else if (*pcbStructInfo < sizeof(int))
2197 *pcbStructInfo = sizeof(int);
2198 SetLastError(ERROR_MORE_DATA);
2199 ret = FALSE;
2201 else
2203 int val;
2204 DWORD i;
2206 *pcbStructInfo = sizeof(int);
2207 if (blob->pbData[blob->cbData - 1] & 0x80)
2209 /* initialize to a negative value to sign-extend */
2210 val = -1;
2212 else
2213 val = 0;
2214 for (i = 0; i < blob->cbData; i++)
2216 val <<= 8;
2217 val |= blob->pbData[blob->cbData - i - 1];
2219 memcpy(pvStructInfo, &val, sizeof(int));
2222 else if (GetLastError() == ERROR_MORE_DATA)
2223 SetLastError(CRYPT_E_ASN1_LARGE);
2224 return ret;
2227 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
2228 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2229 void *pvStructInfo, DWORD *pcbStructInfo)
2231 BOOL ret = FALSE;
2233 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2234 pvStructInfo, *pcbStructInfo);
2236 __TRY
2238 struct AsnDecodeSequenceItem items[] = {
2239 { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
2240 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2241 offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
2242 { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
2243 CRYPT_AsnDecodeInt, sizeof(DWORD),
2244 FALSE, FALSE, 0, 0 },
2247 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2248 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2249 pvStructInfo, pcbStructInfo, NULL);
2251 __EXCEPT_PAGE_FAULT
2253 SetLastError(STATUS_ACCESS_VIOLATION);
2255 __ENDTRY
2256 TRACE("returning %d\n", ret);
2257 return ret;
2260 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
2261 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2262 void *pvStructInfo, DWORD *pcbStructInfo)
2264 BOOL ret = FALSE;
2266 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2267 pvStructInfo, *pcbStructInfo);
2269 __TRY
2271 struct AsnDecodeSequenceItem items[] = {
2272 { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
2273 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2274 offsetof(CAT_NAMEVALUE, pwszTag), 0 },
2275 { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
2276 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2277 { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
2278 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2279 offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
2282 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2283 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2284 pvStructInfo, pcbStructInfo, NULL);
2286 __EXCEPT_PAGE_FAULT
2288 SetLastError(STATUS_ACCESS_VIOLATION);
2290 __ENDTRY
2291 TRACE("returning %d\n", ret);
2292 return ret;
2295 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2296 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2297 void *pvStructInfo, DWORD *pcbStructInfo)
2299 BOOL ret;
2301 if (cbEncoded < 3)
2303 SetLastError(CRYPT_E_ASN1_CORRUPT);
2304 return FALSE;
2306 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2308 SetLastError(CRYPT_E_ASN1_CORRUPT);
2309 return FALSE;
2311 if (pbEncoded[1] > 1)
2313 SetLastError(CRYPT_E_ASN1_CORRUPT);
2314 return FALSE;
2316 if (!pvStructInfo)
2318 *pcbStructInfo = sizeof(BOOL);
2319 ret = TRUE;
2321 else if (*pcbStructInfo < sizeof(BOOL))
2323 *pcbStructInfo = sizeof(BOOL);
2324 SetLastError(ERROR_MORE_DATA);
2325 ret = FALSE;
2327 else
2329 *pcbStructInfo = sizeof(BOOL);
2330 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2331 ret = TRUE;
2333 TRACE("returning %d (%08x)\n", ret, GetLastError());
2334 return ret;
2337 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType,
2338 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2339 void *pvStructInfo, DWORD *pcbStructInfo)
2341 BOOL ret = FALSE;
2343 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2344 pvStructInfo, *pcbStructInfo);
2346 __TRY
2348 struct AsnDecodeSequenceItem items[] = {
2349 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable),
2350 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2351 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria),
2352 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2355 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2356 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2357 pvStructInfo, pcbStructInfo, NULL);
2359 __EXCEPT_PAGE_FAULT
2361 SetLastError(STATUS_ACCESS_VIOLATION);
2363 __ENDTRY
2364 TRACE("returning %d\n", ret);
2365 return ret;