Commit | Line | Data |
---|---|---|
f224b34e | 1 | /* |
716a7405 | 2 | * Copyright 2005-2007 Juan Lang |
f224b34e JL |
3 | * |
4 | * This library is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2.1 of the License, or (at your option) any later version. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
f224b34e JL |
17 | * |
18 | * This file implements ASN.1 DER decoding of a limited set of types. | |
19 | * It isn't a full ASN.1 implementation. Microsoft implements BER | |
716a7405 JL |
20 | * encoding of many of the basic types in msasn1.dll, but that interface isn't |
21 | * implemented, so I implement them here. | |
f224b34e JL |
22 | * |
23 | * References: | |
24 | * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski | |
25 | * (available online, look for a PDF copy as the HTML versions tend to have | |
26 | * translation errors.) | |
27 | * | |
28 | * RFC3280, http://www.faqs.org/rfcs/rfc3280.html | |
29 | * | |
716a7405 | 30 | * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject" |
f224b34e JL |
31 | */ |
32 | ||
dee7722b BJ |
33 | #include "config.h" |
34 | #include "wine/port.h" | |
35 | ||
f224b34e JL |
36 | #include <assert.h> |
37 | #include <stdarg.h> | |
38 | #include <stdio.h> | |
39 | #include <stdlib.h> | |
40 | ||
41 | #define NONAMELESSUNION | |
42 | ||
43 | #include "windef.h" | |
44 | #include "winbase.h" | |
f224b34e | 45 | #include "wincrypt.h" |
ead21189 | 46 | #include "winnls.h" |
f224b34e JL |
47 | #include "snmp.h" |
48 | #include "wine/debug.h" | |
49 | #include "wine/exception.h" | |
50 | #include "crypt32_private.h" | |
51 | ||
52 | /* This is a bit arbitrary, but to set some limit: */ | |
53 | #define MAX_ENCODED_LEN 0x02000000 | |
54 | ||
55 | #define ASN_FLAGS_MASK 0xe0 | |
56 | #define ASN_TYPE_MASK 0x1f | |
57 | ||
53087dbe JL |
58 | WINE_DEFAULT_DEBUG_CHANNEL(cryptasn); |
59 | WINE_DECLARE_DEBUG_CHANNEL(crypt); | |
f224b34e JL |
60 | |
61 | struct GenericArray | |
62 | { | |
63 | DWORD cItems; | |
64 | BYTE *rgItems; | |
65 | }; | |
66 | ||
67 | typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *, | |
68 | DWORD, DWORD, void *, DWORD *); | |
69 | typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *, | |
70 | DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *); | |
71 | ||
731d37b0 JL |
72 | /* Internal decoders don't do memory allocation or exception handling, and |
73 | * they report how many bytes they decoded. | |
74 | */ | |
75 | typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded, | |
76 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); | |
77 | ||
e03864a2 JL |
78 | static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded, |
79 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
80 | DWORD *pcbDecoded); | |
81 | static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded, | |
82 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
83 | DWORD *pcbDecoded); | |
f224b34e JL |
84 | /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of |
85 | * time, doesn't do memory allocation, and doesn't do exception handling. | |
f224b34e | 86 | */ |
e03864a2 JL |
87 | static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded, |
88 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
89 | DWORD *pcbDecoded); | |
90 | /* Assumes algo->Parameters.pbData is set ahead of time. */ | |
91 | static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded, | |
92 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); | |
93 | static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded, | |
94 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); | |
f224b34e | 95 | /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */ |
e03864a2 JL |
96 | static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded, |
97 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
98 | DWORD *pcbDecoded); | |
99 | static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded, | |
100 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); | |
101 | static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded, | |
102 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); | |
f224b34e JL |
103 | /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData |
104 | * member has been initialized, doesn't do exception handling, and doesn't do | |
9153d39c JL |
105 | * memory allocation. Also doesn't check tag, assumes the caller has checked |
106 | * it. | |
f224b34e | 107 | */ |
e03864a2 JL |
108 | static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded, |
109 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
110 | DWORD *pcbDecoded); | |
f224b34e | 111 | /* Like CRYPT_AsnDecodeInteger, but unsigned. */ |
e03864a2 JL |
112 | static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded, |
113 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
114 | DWORD *pcbDecoded); | |
f224b34e | 115 | |
f224b34e | 116 | /* Gets the number of length bytes from the given (leading) length byte */ |
e747f706 | 117 | #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f)) |
f224b34e JL |
118 | |
119 | /* Helper function to get the encoded length of the data starting at pbEncoded, | |
120 | * where pbEncoded[0] is the tag. If the data are too short to contain a | |
121 | * length or if the length is too large for cbEncoded, sets an appropriate | |
7ecf5bec JL |
122 | * error code and returns FALSE. If the encoded length is unknown due to |
123 | * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH. | |
f224b34e | 124 | */ |
7ecf5bec JL |
125 | static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded, |
126 | DWORD *len) | |
f224b34e JL |
127 | { |
128 | BOOL ret; | |
129 | ||
130 | if (cbEncoded <= 1) | |
131 | { | |
132 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
133 | ret = FALSE; | |
134 | } | |
135 | else if (pbEncoded[1] <= 0x7f) | |
136 | { | |
137 | if (pbEncoded[1] + 1 > cbEncoded) | |
138 | { | |
139 | SetLastError(CRYPT_E_ASN1_EOD); | |
140 | ret = FALSE; | |
141 | } | |
142 | else | |
143 | { | |
144 | *len = pbEncoded[1]; | |
145 | ret = TRUE; | |
146 | } | |
147 | } | |
45652e08 JL |
148 | else if (pbEncoded[1] == 0x80) |
149 | { | |
7ecf5bec JL |
150 | *len = CMSG_INDEFINITE_LENGTH; |
151 | ret = TRUE; | |
45652e08 | 152 | } |
f224b34e JL |
153 | else |
154 | { | |
155 | BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]); | |
156 | ||
157 | if (lenLen > sizeof(DWORD) + 1) | |
158 | { | |
159 | SetLastError(CRYPT_E_ASN1_LARGE); | |
160 | ret = FALSE; | |
161 | } | |
162 | else if (lenLen + 2 > cbEncoded) | |
163 | { | |
164 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
165 | ret = FALSE; | |
166 | } | |
167 | else | |
168 | { | |
169 | DWORD out = 0; | |
170 | ||
171 | pbEncoded += 2; | |
172 | while (--lenLen) | |
173 | { | |
174 | out <<= 8; | |
175 | out |= *pbEncoded++; | |
176 | } | |
177 | if (out + lenLen + 1 > cbEncoded) | |
178 | { | |
179 | SetLastError(CRYPT_E_ASN1_EOD); | |
180 | ret = FALSE; | |
181 | } | |
182 | else | |
183 | { | |
184 | *len = out; | |
185 | ret = TRUE; | |
186 | } | |
187 | } | |
188 | } | |
189 | return ret; | |
190 | } | |
191 | ||
7ecf5bec JL |
192 | /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */ |
193 | static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len) | |
194 | { | |
195 | BOOL ret; | |
196 | ||
197 | if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) && | |
198 | *len == CMSG_INDEFINITE_LENGTH) | |
199 | { | |
200 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
201 | ret = FALSE; | |
202 | } | |
203 | return ret; | |
204 | } | |
205 | ||
f224b34e JL |
206 | /* Helper function to check *pcbStructInfo, set it to the required size, and |
207 | * optionally to allocate memory. Assumes pvStructInfo is not NULL. | |
208 | * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a | |
209 | * pointer to the newly allocated memory. | |
210 | */ | |
211 | static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags, | |
212 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, | |
213 | DWORD bytesNeeded) | |
214 | { | |
215 | BOOL ret = TRUE; | |
216 | ||
217 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
218 | { | |
219 | if (pDecodePara && pDecodePara->pfnAlloc) | |
220 | *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded); | |
221 | else | |
222 | *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded); | |
223 | if (!*(BYTE **)pvStructInfo) | |
224 | ret = FALSE; | |
225 | else | |
226 | *pcbStructInfo = bytesNeeded; | |
227 | } | |
228 | else if (*pcbStructInfo < bytesNeeded) | |
229 | { | |
230 | *pcbStructInfo = bytesNeeded; | |
231 | SetLastError(ERROR_MORE_DATA); | |
232 | ret = FALSE; | |
233 | } | |
234 | return ret; | |
235 | } | |
236 | ||
2e4242b5 JL |
237 | static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv) |
238 | { | |
239 | if (pDecodePara && pDecodePara->pfnFree) | |
240 | pDecodePara->pfnFree(pv); | |
241 | else | |
242 | LocalFree(pv); | |
243 | } | |
244 | ||
8c5bd5f5 JL |
245 | /* Helper function to check *pcbStructInfo and set it to the required size. |
246 | * Assumes pvStructInfo is not NULL. | |
247 | */ | |
248 | static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded) | |
249 | { | |
250 | BOOL ret; | |
251 | ||
252 | if (*pcbStructInfo < bytesNeeded) | |
253 | { | |
254 | *pcbStructInfo = bytesNeeded; | |
255 | SetLastError(ERROR_MORE_DATA); | |
256 | ret = FALSE; | |
257 | } | |
258 | else | |
259 | { | |
260 | *pcbStructInfo = bytesNeeded; | |
261 | ret = TRUE; | |
262 | } | |
263 | return ret; | |
264 | } | |
265 | ||
f224b34e JL |
266 | /* tag: |
267 | * The expected tag of the item. If tag is 0, decodeFunc is called | |
268 | * regardless of the tag value seen. | |
269 | * offset: | |
270 | * A sequence is decoded into a struct. The offset member is the | |
271 | * offset of this item within that struct. | |
272 | * decodeFunc: | |
273 | * The decoder function to use. If this is NULL, then the member isn't | |
274 | * decoded, but minSize space is reserved for it. | |
275 | * minSize: | |
276 | * The minimum amount of space occupied after decoding. You must set this. | |
277 | * optional: | |
278 | * If true, and the tag doesn't match the expected tag for this item, | |
279 | * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is | |
280 | * filled with 0 for this member. | |
8099ff4b | 281 | * hasPointer, pointerOffset: |
f224b34e | 282 | * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to |
8099ff4b | 283 | * the offset within the struct of the data pointer (or to the |
f224b34e JL |
284 | * first data pointer, if more than one exist). |
285 | * size: | |
286 | * Used by CRYPT_AsnDecodeSequence, not for your use. | |
287 | */ | |
288 | struct AsnDecodeSequenceItem | |
289 | { | |
e03864a2 JL |
290 | BYTE tag; |
291 | DWORD offset; | |
292 | InternalDecodeFunc decodeFunc; | |
293 | DWORD minSize; | |
294 | BOOL optional; | |
295 | BOOL hasPointer; | |
296 | DWORD pointerOffset; | |
297 | DWORD size; | |
f224b34e JL |
298 | }; |
299 | ||
8dcd9e42 JL |
300 | /* Decodes the items in a sequence, where the items are described in items, |
301 | * the encoded data are in pbEncoded with length cbEncoded. Decodes into | |
302 | * pvStructInfo. nextData is a pointer to the memory location at which the | |
303 | * first decoded item with a dynamic pointer should point. | |
304 | * Upon decoding, *cbDecoded is the total number of bytes decoded. | |
9d0dccf1 | 305 | * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set. |
8dcd9e42 | 306 | */ |
19fd9872 JL |
307 | static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[], |
308 | DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
309 | void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded) | |
f224b34e JL |
310 | { |
311 | BOOL ret; | |
8dcd9e42 JL |
312 | DWORD i, decoded = 0; |
313 | const BYTE *ptr = pbEncoded; | |
f224b34e | 314 | |
a50d8dc1 JL |
315 | TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded, |
316 | cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded); | |
317 | ||
f224b34e JL |
318 | for (i = 0, ret = TRUE; ret && i < cItem; i++) |
319 | { | |
320 | if (cbEncoded - (ptr - pbEncoded) != 0) | |
321 | { | |
f534a67b | 322 | DWORD itemLen; |
f224b34e | 323 | |
34aaabca | 324 | if ((ret = CRYPT_GetLengthIndefinite(ptr, |
f534a67b | 325 | cbEncoded - (ptr - pbEncoded), &itemLen))) |
f224b34e | 326 | { |
f534a67b | 327 | BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]); |
f224b34e JL |
328 | |
329 | if (ptr[0] == items[i].tag || !items[i].tag) | |
330 | { | |
f534a67b JL |
331 | DWORD itemEncodedLen; |
332 | ||
333 | if (itemLen == CMSG_INDEFINITE_LENGTH) | |
334 | itemEncodedLen = cbEncoded - (ptr - pbEncoded); | |
335 | else | |
336 | itemEncodedLen = 1 + itemLenBytes + itemLen; | |
f224b34e JL |
337 | if (nextData && pvStructInfo && items[i].hasPointer) |
338 | { | |
339 | TRACE("Setting next pointer to %p\n", | |
340 | nextData); | |
341 | *(BYTE **)((BYTE *)pvStructInfo + | |
342 | items[i].pointerOffset) = nextData; | |
343 | } | |
344 | if (items[i].decodeFunc) | |
345 | { | |
f534a67b | 346 | DWORD itemDecoded; |
34aaabca | 347 | |
f224b34e | 348 | if (pvStructInfo) |
f3a1f2bf | 349 | TRACE("decoding item %d\n", i); |
f224b34e | 350 | else |
f3a1f2bf | 351 | TRACE("sizing item %d\n", i); |
f534a67b | 352 | ret = items[i].decodeFunc(ptr, itemEncodedLen, |
e03864a2 | 353 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, |
f224b34e | 354 | pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset |
f534a67b | 355 | : NULL, &items[i].size, &itemDecoded); |
f224b34e JL |
356 | if (ret) |
357 | { | |
f224b34e | 358 | /* Account for alignment padding */ |
cc2059b6 JL |
359 | if (items[i].size % sizeof(DWORD_PTR)) |
360 | items[i].size += sizeof(DWORD_PTR) - | |
361 | items[i].size % sizeof(DWORD_PTR); | |
a50d8dc1 | 362 | TRACE("item %d size: %d\n", i, items[i].size); |
f0509c49 JL |
363 | if (nextData && items[i].hasPointer && |
364 | items[i].size > items[i].minSize) | |
365 | nextData += items[i].size - items[i].minSize; | |
f534a67b | 366 | if (itemDecoded > itemEncodedLen) |
34aaabca JL |
367 | { |
368 | WARN("decoded length %d exceeds encoded %d\n", | |
f534a67b | 369 | itemDecoded, itemEncodedLen); |
34aaabca JL |
370 | SetLastError(CRYPT_E_ASN1_CORRUPT); |
371 | ret = FALSE; | |
372 | } | |
373 | else | |
374 | { | |
9c4c856f JL |
375 | if (itemLen == CMSG_INDEFINITE_LENGTH) |
376 | { | |
377 | if (itemDecoded > itemEncodedLen - 2 || | |
378 | *(ptr + itemDecoded) != 0 || | |
379 | *(ptr + itemDecoded + 1) != 0) | |
380 | { | |
381 | TRACE("expected 0 TLV\n"); | |
382 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
383 | ret = FALSE; | |
384 | } | |
385 | else | |
386 | itemDecoded += 2; | |
387 | } | |
388 | if (ret) | |
389 | { | |
390 | ptr += itemDecoded; | |
391 | decoded += itemDecoded; | |
392 | TRACE("item %d: decoded %d bytes\n", i, | |
393 | itemDecoded); | |
394 | } | |
34aaabca | 395 | } |
f224b34e JL |
396 | } |
397 | else if (items[i].optional && | |
398 | GetLastError() == CRYPT_E_ASN1_BADTAG) | |
399 | { | |
f3a1f2bf | 400 | TRACE("skipping optional item %d\n", i); |
f224b34e JL |
401 | items[i].size = items[i].minSize; |
402 | SetLastError(NOERROR); | |
403 | ret = TRUE; | |
404 | } | |
405 | else | |
f3a1f2bf | 406 | TRACE("item %d failed: %08x\n", i, |
f224b34e JL |
407 | GetLastError()); |
408 | } | |
f534a67b | 409 | else if (itemLen == CMSG_INDEFINITE_LENGTH) |
34aaabca JL |
410 | { |
411 | ERR("can't use indefinite length encoding without a decoder\n"); | |
412 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
413 | ret = FALSE; | |
414 | } | |
f224b34e | 415 | else |
8dcd9e42 | 416 | { |
f534a67b JL |
417 | TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen); |
418 | ptr += itemEncodedLen; | |
419 | decoded += itemEncodedLen; | |
f224b34e | 420 | items[i].size = items[i].minSize; |
8dcd9e42 | 421 | } |
f224b34e JL |
422 | } |
423 | else if (items[i].optional) | |
424 | { | |
f3a1f2bf | 425 | TRACE("skipping optional item %d\n", i); |
f224b34e JL |
426 | items[i].size = items[i].minSize; |
427 | } | |
428 | else | |
429 | { | |
b8ab4621 JL |
430 | TRACE("item %d: tag %02x doesn't match expected %02x\n", |
431 | i, ptr[0], items[i].tag); | |
f224b34e JL |
432 | SetLastError(CRYPT_E_ASN1_BADTAG); |
433 | ret = FALSE; | |
434 | } | |
435 | } | |
436 | } | |
437 | else if (items[i].optional) | |
438 | { | |
f3a1f2bf | 439 | TRACE("missing optional item %d, skipping\n", i); |
f224b34e JL |
440 | items[i].size = items[i].minSize; |
441 | } | |
442 | else | |
443 | { | |
f3a1f2bf | 444 | TRACE("not enough bytes for item %d, failing\n", i); |
f224b34e JL |
445 | SetLastError(CRYPT_E_ASN1_CORRUPT); |
446 | ret = FALSE; | |
447 | } | |
448 | } | |
2e8ae598 | 449 | if (cbDecoded) |
8dcd9e42 | 450 | *cbDecoded = decoded; |
a50d8dc1 | 451 | TRACE("returning %d\n", ret); |
f224b34e JL |
452 | return ret; |
453 | } | |
454 | ||
455 | /* This decodes an arbitrary sequence into a contiguous block of memory | |
456 | * (basically, a struct.) Each element being decoded is described by a struct | |
457 | * AsnDecodeSequenceItem, see above. | |
458 | * startingPointer is an optional pointer to the first place where dynamic | |
459 | * data will be stored. If you know the starting offset, you may pass it | |
460 | * here. Otherwise, pass NULL, and one will be inferred from the items. | |
f224b34e | 461 | */ |
ce47433d JL |
462 | static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[], |
463 | DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
464 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, | |
465 | DWORD *pcbDecoded, void *startingPointer) | |
f224b34e JL |
466 | { |
467 | BOOL ret; | |
468 | ||
f3a1f2bf | 469 | TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded, |
f224b34e JL |
470 | cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo, |
471 | startingPointer); | |
472 | ||
473 | if (pbEncoded[0] == ASN_SEQUENCE) | |
474 | { | |
475 | DWORD dataLen; | |
476 | ||
4fd90dda | 477 | if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) |
f224b34e | 478 | { |
8dcd9e42 JL |
479 | DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded; |
480 | const BYTE *ptr = pbEncoded + 1 + lenBytes; | |
5b092877 | 481 | BOOL indefinite = FALSE; |
f224b34e | 482 | |
8dcd9e42 | 483 | cbEncoded -= 1 + lenBytes; |
4fd90dda | 484 | if (dataLen == CMSG_INDEFINITE_LENGTH) |
5b092877 | 485 | { |
43e6b48b | 486 | dataLen = cbEncoded; |
5b092877 JL |
487 | indefinite = TRUE; |
488 | } | |
4fd90dda | 489 | else if (cbEncoded < dataLen) |
8dcd9e42 JL |
490 | { |
491 | TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen, | |
492 | cbEncoded); | |
493 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
494 | ret = FALSE; | |
495 | } | |
4fd90dda JL |
496 | if (ret) |
497 | { | |
19fd9872 | 498 | ret = CRYPT_AsnDecodeSequenceItems(items, cItem, |
43e6b48b | 499 | ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded); |
4fd90dda JL |
500 | if (ret && dataLen == CMSG_INDEFINITE_LENGTH) |
501 | { | |
502 | if (cbDecoded > cbEncoded - 2) | |
503 | { | |
504 | /* Not enough space for 0 TLV */ | |
505 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
506 | ret = FALSE; | |
507 | } | |
508 | else if (*(ptr + cbDecoded) != 0 || | |
509 | *(ptr + cbDecoded + 1) != 0) | |
510 | { | |
511 | TRACE("expected 0 TLV\n"); | |
512 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
513 | ret = FALSE; | |
514 | } | |
515 | else | |
516 | cbDecoded += 2; | |
517 | } | |
518 | } | |
5b092877 | 519 | if (ret && !indefinite && cbDecoded != dataLen) |
8dcd9e42 | 520 | { |
43e6b48b | 521 | TRACE("expected %d decoded, got %d, failing\n", dataLen, |
8dcd9e42 JL |
522 | cbDecoded); |
523 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
524 | ret = FALSE; | |
525 | } | |
f224b34e JL |
526 | if (ret) |
527 | { | |
8dcd9e42 | 528 | DWORD i, bytesNeeded = 0, structSize = 0; |
f224b34e JL |
529 | |
530 | for (i = 0; i < cItem; i++) | |
531 | { | |
532 | bytesNeeded += items[i].size; | |
533 | structSize += items[i].minSize; | |
534 | } | |
ee28204f | 535 | if (pcbDecoded) |
159a3693 | 536 | *pcbDecoded = 1 + lenBytes + cbDecoded; |
f224b34e JL |
537 | if (!pvStructInfo) |
538 | *pcbStructInfo = bytesNeeded; | |
539 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, | |
540 | pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) | |
541 | { | |
542 | BYTE *nextData; | |
543 | ||
544 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
545 | pvStructInfo = *(BYTE **)pvStructInfo; | |
546 | if (startingPointer) | |
547 | nextData = (BYTE *)startingPointer; | |
548 | else | |
549 | nextData = (BYTE *)pvStructInfo + structSize; | |
550 | memset(pvStructInfo, 0, structSize); | |
19fd9872 | 551 | ret = CRYPT_AsnDecodeSequenceItems(items, cItem, |
43e6b48b | 552 | ptr, dataLen, dwFlags, pvStructInfo, nextData, |
8dcd9e42 | 553 | &cbDecoded); |
2e4242b5 JL |
554 | if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) |
555 | CRYPT_FreeSpace(pDecodePara, pvStructInfo); | |
f224b34e JL |
556 | } |
557 | } | |
558 | } | |
559 | } | |
560 | else | |
561 | { | |
562 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
563 | ret = FALSE; | |
564 | } | |
f3a1f2bf | 565 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
566 | return ret; |
567 | } | |
568 | ||
569 | /* tag: | |
570 | * The expected tag of the entire encoded array (usually a variant | |
2d00a4f0 JL |
571 | * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called |
572 | * regardless of the tag seen. | |
f224b34e JL |
573 | * decodeFunc: |
574 | * used to decode each item in the array | |
575 | * itemSize: | |
576 | * is the minimum size of each decoded item | |
577 | * hasPointer: | |
578 | * indicates whether each item has a dynamic pointer | |
579 | * pointerOffset: | |
580 | * indicates the offset within itemSize at which the pointer exists | |
581 | */ | |
582 | struct AsnArrayDescriptor | |
583 | { | |
731d37b0 JL |
584 | BYTE tag; |
585 | InternalDecodeFunc decodeFunc; | |
586 | DWORD itemSize; | |
587 | BOOL hasPointer; | |
588 | DWORD pointerOffset; | |
f224b34e JL |
589 | }; |
590 | ||
591 | struct AsnArrayItemSize | |
592 | { | |
593 | DWORD encodedLen; | |
594 | DWORD size; | |
595 | }; | |
596 | ||
597 | /* Decodes an array of like types into a struct GenericArray. | |
598 | * The layout and decoding of the array are described by a struct | |
599 | * AsnArrayDescriptor. | |
600 | */ | |
601 | static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc, | |
602 | const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
603 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo, | |
b2f02f3b | 604 | DWORD *pcbDecoded, void *startingPointer) |
f224b34e JL |
605 | { |
606 | BOOL ret = TRUE; | |
607 | ||
f3a1f2bf | 608 | TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded, |
f224b34e JL |
609 | cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo, |
610 | startingPointer); | |
611 | ||
2d00a4f0 | 612 | if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag) |
f224b34e JL |
613 | { |
614 | DWORD dataLen; | |
615 | ||
5d168bd4 | 616 | if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) |
f224b34e | 617 | { |
deb07ccb | 618 | DWORD bytesNeeded, cItems = 0, decoded; |
f224b34e JL |
619 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
620 | /* There can be arbitrarily many items, but there is often only one. | |
621 | */ | |
622 | struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize; | |
623 | ||
deb07ccb | 624 | decoded = 1 + lenBytes; |
f224b34e JL |
625 | bytesNeeded = sizeof(struct GenericArray); |
626 | if (dataLen) | |
627 | { | |
628 | const BYTE *ptr; | |
5d168bd4 | 629 | BOOL doneDecoding = FALSE; |
f224b34e | 630 | |
5d168bd4 | 631 | for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; ) |
f224b34e | 632 | { |
5d168bd4 | 633 | if (dataLen == CMSG_INDEFINITE_LENGTH) |
f224b34e | 634 | { |
5d168bd4 | 635 | if (ptr[0] == 0) |
f224b34e | 636 | { |
5d168bd4 | 637 | doneDecoding = TRUE; |
9c672fea | 638 | if (ptr[1] != 0) |
5d168bd4 JL |
639 | { |
640 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
641 | ret = FALSE; | |
642 | } | |
643 | else | |
644 | decoded += 2; | |
f224b34e | 645 | } |
5d168bd4 JL |
646 | } |
647 | else if (ptr - pbEncoded - 1 - lenBytes >= dataLen) | |
648 | doneDecoding = TRUE; | |
649 | if (!doneDecoding) | |
650 | { | |
52be131a | 651 | DWORD itemEncoded, itemDataLen, itemDecoded, size = 0; |
5d168bd4 JL |
652 | |
653 | /* Each item decoded may not tolerate extraneous bytes, | |
52be131a | 654 | * so get the length of the next element if known. |
5d168bd4 | 655 | */ |
52be131a JL |
656 | if ((ret = CRYPT_GetLengthIndefinite(ptr, |
657 | cbEncoded - (ptr - pbEncoded), &itemDataLen))) | |
658 | { | |
659 | if (itemDataLen == CMSG_INDEFINITE_LENGTH) | |
660 | itemEncoded = cbEncoded - (ptr - pbEncoded); | |
661 | else | |
9c672fea JL |
662 | itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) + |
663 | itemDataLen; | |
52be131a | 664 | } |
5d168bd4 | 665 | if (ret) |
52be131a | 666 | ret = arrayDesc->decodeFunc(ptr, itemEncoded, |
5d168bd4 JL |
667 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size, |
668 | &itemDecoded); | |
669 | if (ret) | |
f224b34e | 670 | { |
5d168bd4 JL |
671 | cItems++; |
672 | if (itemSizes != &itemSize) | |
673 | itemSizes = CryptMemRealloc(itemSizes, | |
674 | cItems * sizeof(struct AsnArrayItemSize)); | |
675 | else if (cItems > 1) | |
676 | { | |
677 | itemSizes = | |
678 | CryptMemAlloc( | |
679 | cItems * sizeof(struct AsnArrayItemSize)); | |
680 | if (itemSizes) | |
681 | memcpy(itemSizes, &itemSize, | |
682 | sizeof(itemSize)); | |
683 | } | |
684 | if (itemSizes) | |
685 | { | |
686 | decoded += itemDecoded; | |
52be131a | 687 | itemSizes[cItems - 1].encodedLen = itemEncoded; |
5d168bd4 JL |
688 | itemSizes[cItems - 1].size = size; |
689 | bytesNeeded += size; | |
52be131a | 690 | ptr += itemEncoded; |
5d168bd4 JL |
691 | } |
692 | else | |
693 | ret = FALSE; | |
f224b34e | 694 | } |
f224b34e JL |
695 | } |
696 | } | |
697 | } | |
698 | if (ret) | |
699 | { | |
159a3693 JL |
700 | if (pcbDecoded) |
701 | *pcbDecoded = decoded; | |
f224b34e JL |
702 | if (!pvStructInfo) |
703 | *pcbStructInfo = bytesNeeded; | |
704 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, | |
705 | pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) | |
706 | { | |
707 | DWORD i; | |
708 | BYTE *nextData; | |
709 | const BYTE *ptr; | |
710 | struct GenericArray *array; | |
711 | ||
712 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
713 | pvStructInfo = *(BYTE **)pvStructInfo; | |
714 | array = (struct GenericArray *)pvStructInfo; | |
715 | array->cItems = cItems; | |
716 | if (startingPointer) | |
717 | array->rgItems = startingPointer; | |
718 | else | |
719 | array->rgItems = (BYTE *)array + | |
720 | sizeof(struct GenericArray); | |
a06caa0e | 721 | nextData = array->rgItems + |
f224b34e JL |
722 | array->cItems * arrayDesc->itemSize; |
723 | for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret && | |
724 | i < cItems && ptr - pbEncoded - 1 - lenBytes < | |
725 | dataLen; i++) | |
726 | { | |
0bd29b12 JL |
727 | DWORD itemDecoded; |
728 | ||
f224b34e JL |
729 | if (arrayDesc->hasPointer) |
730 | *(BYTE **)(array->rgItems + i * arrayDesc->itemSize | |
731 | + arrayDesc->pointerOffset) = nextData; | |
731d37b0 | 732 | ret = arrayDesc->decodeFunc(ptr, |
f224b34e | 733 | itemSizes[i].encodedLen, |
731d37b0 | 734 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, |
f224b34e | 735 | array->rgItems + i * arrayDesc->itemSize, |
0bd29b12 | 736 | &itemSizes[i].size, &itemDecoded); |
f224b34e JL |
737 | if (ret) |
738 | { | |
f224b34e | 739 | nextData += itemSizes[i].size - arrayDesc->itemSize; |
0bd29b12 | 740 | ptr += itemDecoded; |
f224b34e JL |
741 | } |
742 | } | |
2e4242b5 JL |
743 | if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG)) |
744 | CRYPT_FreeSpace(pDecodePara, pvStructInfo); | |
f224b34e JL |
745 | } |
746 | } | |
747 | if (itemSizes != &itemSize) | |
748 | CryptMemFree(itemSizes); | |
749 | } | |
750 | } | |
751 | else | |
752 | { | |
753 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
754 | ret = FALSE; | |
755 | } | |
756 | return ret; | |
757 | } | |
758 | ||
759 | /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by | |
760 | * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set | |
761 | * to CRYPT_E_ASN1_CORRUPT. | |
762 | * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData | |
763 | * set! | |
764 | */ | |
e03864a2 JL |
765 | static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded, |
766 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
767 | { |
768 | BOOL ret; | |
769 | DWORD dataLen; | |
770 | ||
771 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
772 | { | |
773 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
774 | DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB); | |
775 | ||
776 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
777 | bytesNeeded += 1 + lenBytes + dataLen; | |
778 | ||
2e8ae598 JL |
779 | if (pcbDecoded) |
780 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
781 | if (!pvStructInfo) |
782 | *pcbStructInfo = bytesNeeded; | |
8c5bd5f5 | 783 | else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded))) |
f224b34e JL |
784 | { |
785 | CRYPT_DER_BLOB *blob; | |
786 | ||
787 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
788 | pvStructInfo = *(BYTE **)pvStructInfo; | |
789 | blob = (CRYPT_DER_BLOB *)pvStructInfo; | |
790 | blob->cbData = 1 + lenBytes + dataLen; | |
791 | if (blob->cbData) | |
792 | { | |
793 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) | |
794 | blob->pbData = (BYTE *)pbEncoded; | |
795 | else | |
796 | { | |
797 | assert(blob->pbData); | |
798 | memcpy(blob->pbData, pbEncoded, blob->cbData); | |
799 | } | |
800 | } | |
801 | else | |
802 | { | |
803 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
804 | ret = FALSE; | |
805 | } | |
806 | } | |
807 | } | |
808 | return ret; | |
809 | } | |
810 | ||
811 | /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */ | |
e03864a2 JL |
812 | static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded, |
813 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
814 | DWORD *pcbDecoded) | |
f224b34e JL |
815 | { |
816 | BOOL ret; | |
817 | ||
e03864a2 JL |
818 | TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags, |
819 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
820 | |
821 | /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in- | |
822 | * place. | |
823 | */ | |
e03864a2 JL |
824 | ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, |
825 | dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo, | |
826 | pcbDecoded); | |
f224b34e JL |
827 | if (ret && pvStructInfo) |
828 | { | |
829 | CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo; | |
830 | ||
831 | if (blob->cbData) | |
832 | { | |
833 | DWORD i; | |
834 | BYTE temp; | |
835 | ||
836 | for (i = 0; i < blob->cbData / 2; i++) | |
837 | { | |
838 | temp = blob->pbData[i]; | |
839 | blob->pbData[i] = blob->pbData[blob->cbData - i - 1]; | |
840 | blob->pbData[blob->cbData - i - 1] = temp; | |
841 | } | |
842 | } | |
843 | } | |
f3a1f2bf | 844 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
845 | return ret; |
846 | } | |
847 | ||
1811acc2 | 848 | static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType, |
f224b34e JL |
849 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, |
850 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
851 | { | |
852 | BOOL ret = TRUE; | |
853 | ||
f3a1f2bf | 854 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
855 | pDecodePara, pvStructInfo, *pcbStructInfo); |
856 | ||
857 | __TRY | |
858 | { | |
859 | struct AsnDecodeSequenceItem items[] = { | |
860 | { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned), | |
861 | CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, | |
862 | offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 }, | |
863 | { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO, | |
864 | SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, | |
865 | sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, | |
866 | offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 }, | |
867 | { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature), | |
868 | CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, | |
869 | offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 }, | |
870 | }; | |
871 | ||
872 | if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG) | |
873 | items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal; | |
ce47433d JL |
874 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
875 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
876 | pcbStructInfo, NULL, NULL); | |
f224b34e JL |
877 | } |
878 | __EXCEPT_PAGE_FAULT | |
879 | { | |
880 | SetLastError(STATUS_ACCESS_VIOLATION); | |
881 | ret = FALSE; | |
882 | } | |
883 | __ENDTRY | |
1811acc2 | 884 | |
f3a1f2bf | 885 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
886 | return ret; |
887 | } | |
888 | ||
e03864a2 JL |
889 | static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded, |
890 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
891 | { |
892 | BOOL ret; | |
893 | DWORD dataLen; | |
894 | ||
895 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
896 | { | |
897 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
898 | ||
e03864a2 | 899 | ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen, |
2e8ae598 JL |
900 | dwFlags, pvStructInfo, pcbStructInfo, NULL); |
901 | if (pcbDecoded) | |
902 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
903 | } |
904 | return ret; | |
905 | } | |
906 | ||
e03864a2 JL |
907 | static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded, |
908 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
909 | { |
910 | BOOL ret; | |
911 | ||
912 | struct AsnDecodeSequenceItem items[] = { | |
913 | { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore), | |
e03864a2 | 914 | CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, |
f224b34e | 915 | { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter), |
e03864a2 | 916 | CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, |
f224b34e JL |
917 | }; |
918 | ||
ce47433d | 919 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
e03864a2 JL |
920 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, |
921 | pcbDecoded, NULL); | |
f224b34e JL |
922 | return ret; |
923 | } | |
924 | ||
e03864a2 JL |
925 | static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded, |
926 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
927 | DWORD *pcbDecoded) | |
f224b34e JL |
928 | { |
929 | BOOL ret; | |
930 | DWORD dataLen; | |
931 | ||
932 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
933 | { | |
934 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
935 | ||
e03864a2 | 936 | ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes, |
2e8ae598 JL |
937 | dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL); |
938 | if (ret && pcbDecoded) | |
939 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
940 | } |
941 | return ret; | |
942 | } | |
943 | ||
944 | static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType, | |
945 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
946 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
947 | { | |
948 | BOOL ret = TRUE; | |
1811acc2 JL |
949 | struct AsnDecodeSequenceItem items[] = { |
950 | { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion), | |
951 | CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 }, | |
952 | { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber), | |
953 | CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, | |
954 | TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 }, | |
955 | { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm), | |
956 | CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), | |
957 | FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 }, | |
958 | { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob, | |
959 | sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, | |
960 | Issuer.pbData) }, | |
961 | { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore), | |
962 | CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, | |
963 | FALSE, 0 }, | |
964 | { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob, | |
965 | sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, | |
966 | Subject.pbData) }, | |
967 | { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo), | |
968 | CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO), | |
969 | FALSE, TRUE, offsetof(CERT_INFO, | |
970 | SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 }, | |
971 | { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId), | |
972 | CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, | |
973 | offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 }, | |
974 | { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId), | |
975 | CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, | |
976 | offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 }, | |
977 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension), | |
978 | CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE, | |
979 | offsetof(CERT_INFO, rgExtension), 0 }, | |
980 | }; | |
981 | ||
f3a1f2bf | 982 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
1811acc2 JL |
983 | pDecodePara, pvStructInfo, *pcbStructInfo); |
984 | ||
ce47433d JL |
985 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
986 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, | |
987 | NULL, NULL); | |
8dcd9e42 JL |
988 | if (ret && pvStructInfo) |
989 | { | |
990 | CERT_INFO *info; | |
991 | ||
992 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
993 | info = *(CERT_INFO **)pvStructInfo; | |
994 | else | |
995 | info = (CERT_INFO *)pvStructInfo; | |
996 | if (!info->SerialNumber.cbData || !info->Issuer.cbData || | |
997 | !info->Subject.cbData) | |
998 | { | |
999 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
1000 | /* Don't need to deallocate, because it should have failed on the | |
1001 | * first pass (and no memory was allocated.) | |
1002 | */ | |
1003 | ret = FALSE; | |
1004 | } | |
1005 | } | |
1811acc2 | 1006 | |
f3a1f2bf | 1007 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
1811acc2 JL |
1008 | return ret; |
1009 | } | |
1010 | ||
1011 | static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType, | |
1012 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1013 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1014 | { | |
d7115ce3 | 1015 | BOOL ret = FALSE; |
f224b34e | 1016 | |
f3a1f2bf | 1017 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
1018 | pDecodePara, pvStructInfo, *pcbStructInfo); |
1019 | ||
1020 | __TRY | |
1021 | { | |
1811acc2 | 1022 | DWORD size = 0; |
f224b34e | 1023 | |
d7115ce3 JL |
1024 | /* Unless told not to, first try to decode it as a signed cert. */ |
1025 | if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG)) | |
1811acc2 | 1026 | { |
d7115ce3 JL |
1027 | PCERT_SIGNED_CONTENT_INFO signedCert = NULL; |
1028 | ||
1029 | ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, | |
1030 | X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, | |
1031 | (BYTE *)&signedCert, &size); | |
1032 | if (ret) | |
1033 | { | |
1034 | size = 0; | |
1035 | ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType, | |
1036 | X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData, | |
1037 | signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, | |
1038 | pvStructInfo, pcbStructInfo); | |
1039 | LocalFree(signedCert); | |
1040 | } | |
1811acc2 JL |
1041 | } |
1042 | /* Failing that, try it as an unsigned cert */ | |
1043 | if (!ret) | |
1044 | { | |
1045 | size = 0; | |
1046 | ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType, | |
1047 | X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags, | |
1048 | pDecodePara, pvStructInfo, pcbStructInfo); | |
1049 | } | |
f224b34e JL |
1050 | } |
1051 | __EXCEPT_PAGE_FAULT | |
1052 | { | |
1053 | SetLastError(STATUS_ACCESS_VIOLATION); | |
f224b34e JL |
1054 | } |
1055 | __ENDTRY | |
1811acc2 | 1056 | |
f3a1f2bf | 1057 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
1058 | return ret; |
1059 | } | |
1060 | ||
731d37b0 JL |
1061 | static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded, |
1062 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
1063 | { |
1064 | BOOL ret; | |
1065 | struct AsnDecodeSequenceItem items[] = { | |
1066 | { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber), | |
1067 | CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, | |
1068 | offsetof(CRL_ENTRY, SerialNumber.pbData), 0 }, | |
e03864a2 JL |
1069 | { 0, offsetof(CRL_ENTRY, RevocationDate), |
1070 | CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 }, | |
f224b34e JL |
1071 | { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension), |
1072 | CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE, | |
1073 | offsetof(CRL_ENTRY, rgExtension), 0 }, | |
1074 | }; | |
1075 | PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo; | |
1076 | ||
f3a1f2bf | 1077 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry, |
f224b34e JL |
1078 | *pcbStructInfo); |
1079 | ||
ce47433d JL |
1080 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
1081 | pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded, | |
f3490f3e | 1082 | entry ? entry->SerialNumber.pbData : NULL); |
c5d5c5b6 JL |
1083 | if (ret && entry && !entry->SerialNumber.cbData) |
1084 | { | |
1085 | WARN("empty CRL entry serial number\n"); | |
1086 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
1087 | ret = FALSE; | |
1088 | } | |
f224b34e JL |
1089 | return ret; |
1090 | } | |
1091 | ||
1092 | /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has | |
1093 | * been set prior to calling. | |
1094 | */ | |
e03864a2 JL |
1095 | static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded, |
1096 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
1097 | { |
1098 | BOOL ret; | |
1099 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
1100 | CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE, | |
1101 | offsetof(CRL_ENTRY, SerialNumber.pbData) }; | |
1102 | struct GenericArray *entries = (struct GenericArray *)pvStructInfo; | |
1103 | ||
e03864a2 JL |
1104 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
1105 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
1106 | |
1107 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 1108 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
f224b34e | 1109 | entries ? entries->rgItems : NULL); |
f3a1f2bf | 1110 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
1111 | return ret; |
1112 | } | |
1113 | ||
1114 | static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType, | |
1115 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1116 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1811acc2 JL |
1117 | { |
1118 | struct AsnDecodeSequenceItem items[] = { | |
1119 | { ASN_INTEGER, offsetof(CRL_INFO, dwVersion), | |
89a541a4 | 1120 | CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 }, |
1811acc2 JL |
1121 | { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm), |
1122 | CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), | |
1123 | FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 }, | |
1124 | { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob, | |
1125 | sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO, | |
1126 | Issuer.pbData) }, | |
e03864a2 | 1127 | { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal, |
1811acc2 | 1128 | sizeof(FILETIME), FALSE, FALSE, 0 }, |
e03864a2 | 1129 | { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal, |
1811acc2 JL |
1130 | sizeof(FILETIME), TRUE, FALSE, 0 }, |
1131 | { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry), | |
1132 | CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE, | |
1133 | offsetof(CRL_INFO, rgCRLEntry), 0 }, | |
1134 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension), | |
1135 | CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE, | |
1136 | offsetof(CRL_INFO, rgExtension), 0 }, | |
1137 | }; | |
1138 | BOOL ret = TRUE; | |
1139 | ||
f3a1f2bf | 1140 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
1811acc2 JL |
1141 | pDecodePara, pvStructInfo, *pcbStructInfo); |
1142 | ||
ce47433d JL |
1143 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
1144 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, | |
1145 | NULL, NULL); | |
1811acc2 | 1146 | |
f3a1f2bf | 1147 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
1811acc2 JL |
1148 | return ret; |
1149 | } | |
1150 | ||
1151 | static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType, | |
1152 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1153 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
f224b34e | 1154 | { |
d7115ce3 | 1155 | BOOL ret = FALSE; |
f224b34e | 1156 | |
f3a1f2bf | 1157 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
1158 | pDecodePara, pvStructInfo, *pcbStructInfo); |
1159 | ||
1160 | __TRY | |
1161 | { | |
1811acc2 | 1162 | DWORD size = 0; |
f224b34e | 1163 | |
d7115ce3 JL |
1164 | /* Unless told not to, first try to decode it as a signed crl. */ |
1165 | if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG)) | |
1811acc2 | 1166 | { |
d7115ce3 JL |
1167 | PCERT_SIGNED_CONTENT_INFO signedCrl = NULL; |
1168 | ||
1169 | ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, | |
1170 | X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, | |
1171 | (BYTE *)&signedCrl, &size); | |
1172 | if (ret) | |
1173 | { | |
1174 | size = 0; | |
1175 | ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType, | |
1176 | X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData, | |
1177 | signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara, | |
1178 | pvStructInfo, pcbStructInfo); | |
1179 | LocalFree(signedCrl); | |
1180 | } | |
1811acc2 JL |
1181 | } |
1182 | /* Failing that, try it as an unsigned crl */ | |
1183 | if (!ret) | |
1184 | { | |
1185 | size = 0; | |
1186 | ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType, | |
1187 | X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded, | |
1188 | dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); | |
1189 | } | |
f224b34e JL |
1190 | } |
1191 | __EXCEPT_PAGE_FAULT | |
1192 | { | |
1193 | SetLastError(STATUS_ACCESS_VIOLATION); | |
f224b34e JL |
1194 | } |
1195 | __ENDTRY | |
1196 | ||
f3a1f2bf | 1197 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
1198 | return ret; |
1199 | } | |
1200 | ||
1dd1c6c2 JL |
1201 | static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded, |
1202 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
1203 | { |
1204 | BOOL ret = TRUE; | |
005b50e9 | 1205 | DWORD dataLen; |
f224b34e | 1206 | |
1dd1c6c2 JL |
1207 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
1208 | pvStructInfo, *pcbStructInfo); | |
f224b34e | 1209 | |
005b50e9 | 1210 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) |
f224b34e | 1211 | { |
005b50e9 JL |
1212 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
1213 | DWORD bytesNeeded = sizeof(LPSTR); | |
f224b34e | 1214 | |
005b50e9 | 1215 | if (dataLen) |
f224b34e | 1216 | { |
005b50e9 JL |
1217 | /* The largest possible string for the first two components |
1218 | * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough. | |
1219 | */ | |
1220 | char firstTwo[6]; | |
1221 | const BYTE *ptr; | |
1222 | ||
1223 | snprintf(firstTwo, sizeof(firstTwo), "%d.%d", | |
1224 | pbEncoded[1 + lenBytes] / 40, | |
1225 | pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40) | |
1226 | * 40); | |
1227 | bytesNeeded += strlen(firstTwo) + 1; | |
1228 | for (ptr = pbEncoded + 2 + lenBytes; ret && | |
1229 | ptr - pbEncoded - 1 - lenBytes < dataLen; ) | |
1230 | { | |
1231 | /* large enough for ".4000000" */ | |
1232 | char str[9]; | |
1233 | int val = 0; | |
f224b34e | 1234 | |
005b50e9 JL |
1235 | while (ptr - pbEncoded - 1 - lenBytes < dataLen && |
1236 | (*ptr & 0x80)) | |
1237 | { | |
1238 | val <<= 7; | |
1239 | val |= *ptr & 0x7f; | |
1240 | ptr++; | |
1241 | } | |
1242 | if (ptr - pbEncoded - 1 - lenBytes >= dataLen || | |
1243 | (*ptr & 0x80)) | |
1244 | { | |
1245 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
1246 | ret = FALSE; | |
1247 | } | |
1248 | else | |
1249 | { | |
1250 | val <<= 7; | |
1251 | val |= *ptr++; | |
1252 | snprintf(str, sizeof(str), ".%d", val); | |
1253 | bytesNeeded += strlen(str); | |
1254 | } | |
1255 | } | |
1256 | } | |
159a3693 JL |
1257 | if (pcbDecoded) |
1258 | *pcbDecoded = 1 + lenBytes + dataLen; | |
005b50e9 JL |
1259 | if (!pvStructInfo) |
1260 | *pcbStructInfo = bytesNeeded; | |
1261 | else if (*pcbStructInfo < bytesNeeded) | |
1262 | { | |
1263 | *pcbStructInfo = bytesNeeded; | |
1264 | SetLastError(ERROR_MORE_DATA); | |
1265 | ret = FALSE; | |
1266 | } | |
1267 | else | |
1268 | { | |
f224b34e JL |
1269 | if (dataLen) |
1270 | { | |
f224b34e | 1271 | const BYTE *ptr; |
005b50e9 | 1272 | LPSTR pszObjId = *(LPSTR *)pvStructInfo; |
f224b34e | 1273 | |
005b50e9 JL |
1274 | *pszObjId = 0; |
1275 | sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40, | |
1276 | pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / | |
1277 | 40) * 40); | |
1278 | pszObjId += strlen(pszObjId); | |
f224b34e JL |
1279 | for (ptr = pbEncoded + 2 + lenBytes; ret && |
1280 | ptr - pbEncoded - 1 - lenBytes < dataLen; ) | |
1281 | { | |
f224b34e JL |
1282 | int val = 0; |
1283 | ||
1284 | while (ptr - pbEncoded - 1 - lenBytes < dataLen && | |
1285 | (*ptr & 0x80)) | |
1286 | { | |
1287 | val <<= 7; | |
1288 | val |= *ptr & 0x7f; | |
1289 | ptr++; | |
1290 | } | |
005b50e9 JL |
1291 | val <<= 7; |
1292 | val |= *ptr++; | |
1293 | sprintf(pszObjId, ".%d", val); | |
1294 | pszObjId += strlen(pszObjId); | |
f224b34e JL |
1295 | } |
1296 | } | |
f224b34e | 1297 | else |
005b50e9 JL |
1298 | *(LPSTR *)pvStructInfo = NULL; |
1299 | *pcbStructInfo = bytesNeeded; | |
1300 | } | |
1301 | } | |
1302 | return ret; | |
1303 | } | |
f224b34e | 1304 | |
731d37b0 JL |
1305 | static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded, |
1306 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
005b50e9 JL |
1307 | { |
1308 | BOOL ret; | |
f224b34e | 1309 | |
731d37b0 JL |
1310 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
1311 | pvStructInfo, *pcbStructInfo); | |
005b50e9 JL |
1312 | |
1313 | if (pbEncoded[0] == ASN_OBJECTIDENTIFIER) | |
1dd1c6c2 JL |
1314 | ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags, |
1315 | pvStructInfo, pcbStructInfo, pcbDecoded); | |
005b50e9 JL |
1316 | else |
1317 | { | |
1318 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
1319 | ret = FALSE; | |
f224b34e JL |
1320 | } |
1321 | return ret; | |
1322 | } | |
1323 | ||
1324 | /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set | |
1325 | * ahead of time! | |
1326 | */ | |
731d37b0 JL |
1327 | static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded, |
1328 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
1329 | { |
1330 | struct AsnDecodeSequenceItem items[] = { | |
1331 | { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId), | |
e03864a2 | 1332 | CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, |
f224b34e JL |
1333 | offsetof(CERT_EXTENSION, pszObjId), 0 }, |
1334 | { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool, | |
1335 | sizeof(BOOL), TRUE, FALSE, 0, 0 }, | |
1336 | { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value), | |
1337 | CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, | |
1338 | offsetof(CERT_EXTENSION, Value.pbData) }, | |
1339 | }; | |
1340 | BOOL ret = TRUE; | |
1341 | PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo; | |
1342 | ||
f3a1f2bf | 1343 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext, |
f224b34e JL |
1344 | *pcbStructInfo); |
1345 | ||
1346 | if (ext) | |
1347 | TRACE("ext->pszObjId is %p\n", ext->pszObjId); | |
ce47433d JL |
1348 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
1349 | pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo, | |
1350 | pcbDecoded, ext ? ext->pszObjId : NULL); | |
f224b34e JL |
1351 | if (ext) |
1352 | TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId, | |
1353 | debugstr_a(ext->pszObjId)); | |
f3a1f2bf | 1354 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
1355 | return ret; |
1356 | } | |
1357 | ||
e03864a2 JL |
1358 | static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded, |
1359 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
1360 | DWORD *pcbDecoded) | |
f224b34e JL |
1361 | { |
1362 | BOOL ret = TRUE; | |
1363 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
1364 | CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE, | |
1365 | offsetof(CERT_EXTENSION, pszObjId) }; | |
1366 | PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo; | |
1367 | ||
e03864a2 JL |
1368 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
1369 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
1370 | |
1371 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 1372 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
b2f02f3b | 1373 | exts ? exts->rgExtension : NULL); |
f224b34e JL |
1374 | return ret; |
1375 | } | |
1376 | ||
1377 | static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType, | |
1378 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1379 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1380 | { | |
1381 | BOOL ret = TRUE; | |
1382 | ||
1383 | __TRY | |
1384 | { | |
e03864a2 JL |
1385 | ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded, |
1386 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); | |
f224b34e JL |
1387 | if (ret && pvStructInfo) |
1388 | { | |
1389 | ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, | |
1390 | pcbStructInfo, *pcbStructInfo); | |
1391 | if (ret) | |
1392 | { | |
1393 | CERT_EXTENSIONS *exts; | |
1394 | ||
1395 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
1396 | pvStructInfo = *(BYTE **)pvStructInfo; | |
1397 | exts = (CERT_EXTENSIONS *)pvStructInfo; | |
1398 | exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts + | |
1399 | sizeof(CERT_EXTENSIONS)); | |
e03864a2 JL |
1400 | ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded, |
1401 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
1402 | pcbStructInfo, NULL); | |
f224b34e JL |
1403 | } |
1404 | } | |
1405 | } | |
1406 | __EXCEPT_PAGE_FAULT | |
1407 | { | |
1408 | SetLastError(STATUS_ACCESS_VIOLATION); | |
1409 | ret = FALSE; | |
1410 | } | |
1411 | __ENDTRY | |
1412 | return ret; | |
1413 | } | |
1414 | ||
1415 | /* Warning: this assumes the address of value->Value.pbData is already set, in | |
1416 | * order to avoid overwriting memory. (In some cases, it may change it, if it | |
1417 | * doesn't copy anything to memory.) Be sure to set it correctly! | |
1418 | */ | |
e03864a2 JL |
1419 | static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded, |
1420 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
1421 | DWORD *pcbDecoded) | |
f224b34e JL |
1422 | { |
1423 | BOOL ret = TRUE; | |
a7f6a012 JL |
1424 | DWORD dataLen; |
1425 | CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo; | |
f224b34e | 1426 | |
a7f6a012 | 1427 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) |
f224b34e | 1428 | { |
a7f6a012 | 1429 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
1eefa005 | 1430 | DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType; |
f224b34e | 1431 | |
a7f6a012 | 1432 | switch (pbEncoded[0]) |
f224b34e | 1433 | { |
1eefa005 JL |
1434 | case ASN_OCTETSTRING: |
1435 | valueType = CERT_RDN_OCTET_STRING; | |
1436 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1437 | bytesNeeded += dataLen; | |
1438 | break; | |
a7f6a012 | 1439 | case ASN_NUMERICSTRING: |
1eefa005 JL |
1440 | valueType = CERT_RDN_NUMERIC_STRING; |
1441 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1442 | bytesNeeded += dataLen; | |
1443 | break; | |
a7f6a012 | 1444 | case ASN_PRINTABLESTRING: |
1eefa005 JL |
1445 | valueType = CERT_RDN_PRINTABLE_STRING; |
1446 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1447 | bytesNeeded += dataLen; | |
1448 | break; | |
a7f6a012 | 1449 | case ASN_IA5STRING: |
1eefa005 JL |
1450 | valueType = CERT_RDN_IA5_STRING; |
1451 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1452 | bytesNeeded += dataLen; | |
1453 | break; | |
dd4bd4ad | 1454 | case ASN_T61STRING: |
1eefa005 JL |
1455 | valueType = CERT_RDN_T61_STRING; |
1456 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1457 | bytesNeeded += dataLen; | |
1458 | break; | |
1459 | case ASN_VIDEOTEXSTRING: | |
1460 | valueType = CERT_RDN_VIDEOTEX_STRING; | |
1461 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1462 | bytesNeeded += dataLen; | |
1463 | break; | |
1464 | case ASN_GRAPHICSTRING: | |
1465 | valueType = CERT_RDN_GRAPHIC_STRING; | |
1466 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1467 | bytesNeeded += dataLen; | |
1468 | break; | |
1469 | case ASN_VISIBLESTRING: | |
1470 | valueType = CERT_RDN_VISIBLE_STRING; | |
1471 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1472 | bytesNeeded += dataLen; | |
1473 | break; | |
1474 | case ASN_GENERALSTRING: | |
1475 | valueType = CERT_RDN_GENERAL_STRING; | |
1476 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
1477 | bytesNeeded += dataLen; | |
1478 | break; | |
1479 | case ASN_UNIVERSALSTRING: | |
1480 | FIXME("ASN_UNIVERSALSTRING: unimplemented\n"); | |
1481 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
a9670e37 | 1482 | return FALSE; |
1eefa005 JL |
1483 | case ASN_BMPSTRING: |
1484 | valueType = CERT_RDN_BMP_STRING; | |
1485 | bytesNeeded += dataLen; | |
1486 | break; | |
1487 | case ASN_UTF8STRING: | |
1488 | valueType = CERT_RDN_UTF8_STRING; | |
1489 | bytesNeeded += MultiByteToWideChar(CP_UTF8, 0, | |
58f9b607 | 1490 | (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2; |
a7f6a012 JL |
1491 | break; |
1492 | default: | |
1eefa005 | 1493 | SetLastError(CRYPT_E_ASN1_BADTAG); |
a9670e37 JH |
1494 | return FALSE; |
1495 | } | |
1496 | ||
2e8ae598 JL |
1497 | if (pcbDecoded) |
1498 | *pcbDecoded = 1 + lenBytes + dataLen; | |
a9670e37 JH |
1499 | if (!value) |
1500 | *pcbStructInfo = bytesNeeded; | |
1501 | else if (*pcbStructInfo < bytesNeeded) | |
1502 | { | |
1503 | *pcbStructInfo = bytesNeeded; | |
1504 | SetLastError(ERROR_MORE_DATA); | |
a7f6a012 JL |
1505 | ret = FALSE; |
1506 | } | |
a9670e37 | 1507 | else |
a7f6a012 | 1508 | { |
a9670e37 JH |
1509 | *pcbStructInfo = bytesNeeded; |
1510 | value->dwValueType = valueType; | |
1511 | if (dataLen) | |
f224b34e | 1512 | { |
a9670e37 | 1513 | DWORD i; |
1eefa005 | 1514 | |
a9670e37 JH |
1515 | assert(value->Value.pbData); |
1516 | switch (pbEncoded[0]) | |
1517 | { | |
1518 | case ASN_OCTETSTRING: | |
1519 | case ASN_NUMERICSTRING: | |
1520 | case ASN_PRINTABLESTRING: | |
1521 | case ASN_IA5STRING: | |
1522 | case ASN_T61STRING: | |
1523 | case ASN_VIDEOTEXSTRING: | |
1524 | case ASN_GRAPHICSTRING: | |
1525 | case ASN_VISIBLESTRING: | |
1526 | case ASN_GENERALSTRING: | |
1527 | value->Value.cbData = dataLen; | |
1528 | if (dataLen) | |
1eefa005 | 1529 | { |
a9670e37 JH |
1530 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) |
1531 | memcpy(value->Value.pbData, | |
1532 | pbEncoded + 1 + lenBytes, dataLen); | |
1533 | else | |
1534 | value->Value.pbData = (LPBYTE)pbEncoded + 1 + | |
1535 | lenBytes; | |
1eefa005 | 1536 | } |
a9670e37 JH |
1537 | break; |
1538 | case ASN_BMPSTRING: | |
1539 | { | |
1540 | LPWSTR str = (LPWSTR)value->Value.pbData; | |
1eefa005 | 1541 | |
a9670e37 JH |
1542 | value->Value.cbData = dataLen; |
1543 | for (i = 0; i < dataLen / 2; i++) | |
1544 | str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) | | |
1545 | pbEncoded[1 + lenBytes + 2 * i + 1]; | |
1546 | break; | |
a7f6a012 | 1547 | } |
a9670e37 | 1548 | case ASN_UTF8STRING: |
a7f6a012 | 1549 | { |
a9670e37 JH |
1550 | LPWSTR str = (LPWSTR)value->Value.pbData; |
1551 | ||
1552 | value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0, | |
58f9b607 | 1553 | (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, |
a9670e37 JH |
1554 | str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2; |
1555 | break; | |
f224b34e | 1556 | } |
a9670e37 JH |
1557 | } |
1558 | } | |
1559 | else | |
1560 | { | |
1561 | value->Value.cbData = 0; | |
1562 | value->Value.pbData = NULL; | |
f224b34e JL |
1563 | } |
1564 | } | |
1565 | } | |
f224b34e JL |
1566 | return ret; |
1567 | } | |
1568 | ||
dd4bd4ad JL |
1569 | static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType, |
1570 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1571 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1572 | { | |
1573 | BOOL ret = TRUE; | |
1574 | ||
1575 | __TRY | |
1576 | { | |
e03864a2 JL |
1577 | ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded, |
1578 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); | |
dd4bd4ad JL |
1579 | if (ret && pvStructInfo) |
1580 | { | |
1581 | ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, | |
1582 | pcbStructInfo, *pcbStructInfo); | |
1583 | if (ret) | |
1584 | { | |
1585 | CERT_NAME_VALUE *value; | |
1586 | ||
1587 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
1588 | pvStructInfo = *(BYTE **)pvStructInfo; | |
1589 | value = (CERT_NAME_VALUE *)pvStructInfo; | |
1590 | value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE)); | |
e03864a2 JL |
1591 | ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded, |
1592 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
1593 | pcbStructInfo, NULL); | |
dd4bd4ad JL |
1594 | } |
1595 | } | |
1596 | } | |
1597 | __EXCEPT_PAGE_FAULT | |
1598 | { | |
1599 | SetLastError(STATUS_ACCESS_VIOLATION); | |
1600 | ret = FALSE; | |
1601 | } | |
1602 | __ENDTRY | |
1603 | return ret; | |
1604 | } | |
1605 | ||
e03864a2 JL |
1606 | static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded, |
1607 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
1608 | DWORD *pcbDecoded) | |
ead21189 JL |
1609 | { |
1610 | BOOL ret = TRUE; | |
1611 | DWORD dataLen; | |
1612 | CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo; | |
1613 | ||
1614 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
1615 | { | |
1616 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
1617 | DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType; | |
1618 | ||
1619 | switch (pbEncoded[0]) | |
1620 | { | |
1621 | case ASN_NUMERICSTRING: | |
1622 | valueType = CERT_RDN_NUMERIC_STRING; | |
8ccbdb80 | 1623 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1624 | break; |
1625 | case ASN_PRINTABLESTRING: | |
1626 | valueType = CERT_RDN_PRINTABLE_STRING; | |
8ccbdb80 | 1627 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1628 | break; |
1629 | case ASN_IA5STRING: | |
1630 | valueType = CERT_RDN_IA5_STRING; | |
8ccbdb80 | 1631 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1632 | break; |
1633 | case ASN_T61STRING: | |
1634 | valueType = CERT_RDN_T61_STRING; | |
8ccbdb80 | 1635 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1636 | break; |
1637 | case ASN_VIDEOTEXSTRING: | |
1638 | valueType = CERT_RDN_VIDEOTEX_STRING; | |
8ccbdb80 | 1639 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1640 | break; |
1641 | case ASN_GRAPHICSTRING: | |
1642 | valueType = CERT_RDN_GRAPHIC_STRING; | |
8ccbdb80 | 1643 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1644 | break; |
1645 | case ASN_VISIBLESTRING: | |
1646 | valueType = CERT_RDN_VISIBLE_STRING; | |
8ccbdb80 | 1647 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1648 | break; |
1649 | case ASN_GENERALSTRING: | |
1650 | valueType = CERT_RDN_GENERAL_STRING; | |
8ccbdb80 | 1651 | bytesNeeded += dataLen * 2; |
ead21189 JL |
1652 | break; |
1653 | case ASN_UNIVERSALSTRING: | |
1654 | valueType = CERT_RDN_UNIVERSAL_STRING; | |
8ccbdb80 | 1655 | bytesNeeded += dataLen / 2; |
ead21189 JL |
1656 | break; |
1657 | case ASN_BMPSTRING: | |
1658 | valueType = CERT_RDN_BMP_STRING; | |
8ccbdb80 | 1659 | bytesNeeded += dataLen; |
ead21189 JL |
1660 | break; |
1661 | case ASN_UTF8STRING: | |
1662 | valueType = CERT_RDN_UTF8_STRING; | |
1663 | bytesNeeded += MultiByteToWideChar(CP_UTF8, 0, | |
58f9b607 | 1664 | (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2; |
ead21189 JL |
1665 | break; |
1666 | default: | |
1667 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
382d0679 JH |
1668 | return FALSE; |
1669 | } | |
1670 | ||
2e8ae598 JL |
1671 | if (pcbDecoded) |
1672 | *pcbDecoded = 1 + lenBytes + dataLen; | |
382d0679 JH |
1673 | if (!value) |
1674 | *pcbStructInfo = bytesNeeded; | |
1675 | else if (*pcbStructInfo < bytesNeeded) | |
1676 | { | |
1677 | *pcbStructInfo = bytesNeeded; | |
1678 | SetLastError(ERROR_MORE_DATA); | |
ead21189 JL |
1679 | ret = FALSE; |
1680 | } | |
382d0679 | 1681 | else |
ead21189 | 1682 | { |
382d0679 JH |
1683 | *pcbStructInfo = bytesNeeded; |
1684 | value->dwValueType = valueType; | |
1685 | if (dataLen) | |
ead21189 | 1686 | { |
382d0679 JH |
1687 | DWORD i; |
1688 | LPWSTR str = (LPWSTR)value->Value.pbData; | |
ead21189 | 1689 | |
382d0679 JH |
1690 | assert(value->Value.pbData); |
1691 | switch (pbEncoded[0]) | |
ead21189 | 1692 | { |
382d0679 JH |
1693 | case ASN_NUMERICSTRING: |
1694 | case ASN_PRINTABLESTRING: | |
1695 | case ASN_IA5STRING: | |
1696 | case ASN_T61STRING: | |
1697 | case ASN_VIDEOTEXSTRING: | |
1698 | case ASN_GRAPHICSTRING: | |
1699 | case ASN_VISIBLESTRING: | |
1700 | case ASN_GENERALSTRING: | |
1701 | value->Value.cbData = dataLen * 2; | |
1702 | for (i = 0; i < dataLen; i++) | |
1703 | str[i] = pbEncoded[1 + lenBytes + i]; | |
1704 | break; | |
1705 | case ASN_UNIVERSALSTRING: | |
1706 | value->Value.cbData = dataLen / 2; | |
1707 | for (i = 0; i < dataLen / 4; i++) | |
1708 | str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8) | |
1709 | | pbEncoded[1 + lenBytes + 2 * i + 3]; | |
1710 | break; | |
1711 | case ASN_BMPSTRING: | |
1712 | value->Value.cbData = dataLen; | |
1713 | for (i = 0; i < dataLen / 2; i++) | |
1714 | str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) | | |
1715 | pbEncoded[1 + lenBytes + 2 * i + 1]; | |
1716 | break; | |
1717 | case ASN_UTF8STRING: | |
1718 | value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0, | |
58f9b607 | 1719 | (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, |
382d0679 JH |
1720 | str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2; |
1721 | break; | |
ead21189 JL |
1722 | } |
1723 | } | |
382d0679 JH |
1724 | else |
1725 | { | |
1726 | value->Value.cbData = 0; | |
1727 | value->Value.pbData = NULL; | |
1728 | } | |
ead21189 JL |
1729 | } |
1730 | } | |
1731 | return ret; | |
1732 | } | |
1733 | ||
1734 | static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType, | |
1735 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1736 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1737 | { | |
1738 | BOOL ret = TRUE; | |
1739 | ||
1740 | __TRY | |
1741 | { | |
e03864a2 JL |
1742 | ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded, |
1743 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); | |
ead21189 JL |
1744 | if (ret && pvStructInfo) |
1745 | { | |
1746 | ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, | |
1747 | pcbStructInfo, *pcbStructInfo); | |
1748 | if (ret) | |
1749 | { | |
1750 | CERT_NAME_VALUE *value; | |
1751 | ||
1752 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
1753 | pvStructInfo = *(BYTE **)pvStructInfo; | |
1754 | value = (CERT_NAME_VALUE *)pvStructInfo; | |
1755 | value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE)); | |
e03864a2 JL |
1756 | ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, |
1757 | cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
1758 | pcbStructInfo, NULL); | |
ead21189 JL |
1759 | } |
1760 | } | |
1761 | } | |
1762 | __EXCEPT_PAGE_FAULT | |
1763 | { | |
1764 | SetLastError(STATUS_ACCESS_VIOLATION); | |
1765 | ret = FALSE; | |
1766 | } | |
1767 | __ENDTRY | |
1768 | return ret; | |
1769 | } | |
1770 | ||
731d37b0 JL |
1771 | static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded, |
1772 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
1773 | { |
1774 | BOOL ret; | |
a7f6a012 JL |
1775 | struct AsnDecodeSequenceItem items[] = { |
1776 | { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId), | |
e03864a2 | 1777 | CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, |
a7f6a012 JL |
1778 | offsetof(CERT_RDN_ATTR, pszObjId), 0 }, |
1779 | { 0, offsetof(CERT_RDN_ATTR, dwValueType), | |
dd4bd4ad | 1780 | CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE), |
a7f6a012 JL |
1781 | FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 }, |
1782 | }; | |
1783 | CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo; | |
f224b34e | 1784 | |
f3a1f2bf | 1785 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
1786 | pvStructInfo, *pcbStructInfo); |
1787 | ||
a7f6a012 JL |
1788 | if (attr) |
1789 | TRACE("attr->pszObjId is %p\n", attr->pszObjId); | |
ce47433d JL |
1790 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
1791 | pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded, | |
1792 | attr ? attr->pszObjId : NULL); | |
a7f6a012 | 1793 | if (attr) |
f224b34e | 1794 | { |
a7f6a012 JL |
1795 | TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId, |
1796 | debugstr_a(attr->pszObjId)); | |
f3a1f2bf | 1797 | TRACE("attr->dwValueType is %d\n", attr->dwValueType); |
f224b34e | 1798 | } |
f3a1f2bf | 1799 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
1800 | return ret; |
1801 | } | |
1802 | ||
731d37b0 JL |
1803 | static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded, |
1804 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
1805 | { |
1806 | BOOL ret = TRUE; | |
a7f6a012 JL |
1807 | struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, |
1808 | CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE, | |
1809 | offsetof(CERT_RDN_ATTR, pszObjId) }; | |
1810 | PCERT_RDN rdn = (PCERT_RDN)pvStructInfo; | |
f224b34e | 1811 | |
a7f6a012 | 1812 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, |
b2f02f3b JL |
1813 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
1814 | rdn ? rdn->rgRDNAttr : NULL); | |
f224b34e JL |
1815 | return ret; |
1816 | } | |
1817 | ||
1818 | static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType, | |
1819 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1820 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1821 | { | |
1822 | BOOL ret = TRUE; | |
1823 | ||
1824 | __TRY | |
1825 | { | |
1826 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
1827 | CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE, | |
1828 | offsetof(CERT_RDN, rgRDNAttr) }; | |
1829 | ||
1830 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
b2f02f3b | 1831 | pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); |
f224b34e JL |
1832 | } |
1833 | __EXCEPT_PAGE_FAULT | |
1834 | { | |
1835 | SetLastError(STATUS_ACCESS_VIOLATION); | |
1836 | ret = FALSE; | |
1837 | } | |
1838 | __ENDTRY | |
1839 | return ret; | |
1840 | } | |
1841 | ||
731d37b0 JL |
1842 | static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded, |
1843 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
1844 | DWORD *pcbDecoded) | |
8ccbdb80 JL |
1845 | { |
1846 | BOOL ret; | |
1847 | struct AsnDecodeSequenceItem items[] = { | |
1848 | { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId), | |
e03864a2 | 1849 | CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, |
8ccbdb80 JL |
1850 | offsetof(CERT_RDN_ATTR, pszObjId), 0 }, |
1851 | { 0, offsetof(CERT_RDN_ATTR, dwValueType), | |
1852 | CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE), | |
1853 | FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 }, | |
1854 | }; | |
1855 | CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo; | |
1856 | ||
f3a1f2bf | 1857 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
8ccbdb80 JL |
1858 | pvStructInfo, *pcbStructInfo); |
1859 | ||
1860 | if (attr) | |
1861 | TRACE("attr->pszObjId is %p\n", attr->pszObjId); | |
ce47433d JL |
1862 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
1863 | pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded, | |
1864 | attr ? attr->pszObjId : NULL); | |
8ccbdb80 JL |
1865 | if (attr) |
1866 | { | |
1867 | TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId, | |
1868 | debugstr_a(attr->pszObjId)); | |
f3a1f2bf | 1869 | TRACE("attr->dwValueType is %d\n", attr->dwValueType); |
8ccbdb80 | 1870 | } |
f3a1f2bf | 1871 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
8ccbdb80 JL |
1872 | return ret; |
1873 | } | |
1874 | ||
731d37b0 JL |
1875 | static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded, |
1876 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
8ccbdb80 JL |
1877 | { |
1878 | BOOL ret = TRUE; | |
1879 | struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, | |
1880 | CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE, | |
1881 | offsetof(CERT_RDN_ATTR, pszObjId) }; | |
1882 | PCERT_RDN rdn = (PCERT_RDN)pvStructInfo; | |
1883 | ||
1884 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
b2f02f3b JL |
1885 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
1886 | rdn ? rdn->rgRDNAttr : NULL); | |
8ccbdb80 JL |
1887 | return ret; |
1888 | } | |
1889 | ||
1890 | static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType, | |
1891 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
1892 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
1893 | { | |
1894 | BOOL ret = TRUE; | |
1895 | ||
1896 | __TRY | |
1897 | { | |
1898 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
1899 | CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE, | |
1900 | offsetof(CERT_RDN, rgRDNAttr) }; | |
1901 | ||
1902 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
b2f02f3b | 1903 | pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); |
8ccbdb80 JL |
1904 | } |
1905 | __EXCEPT_PAGE_FAULT | |
1906 | { | |
1907 | SetLastError(STATUS_ACCESS_VIOLATION); | |
1908 | ret = FALSE; | |
1909 | } | |
1910 | __ENDTRY | |
1911 | return ret; | |
1912 | } | |
1913 | ||
9c4c856f JL |
1914 | static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded, |
1915 | DWORD *pcbDecoded) | |
1916 | { | |
1917 | BOOL ret = TRUE, done = FALSE; | |
1918 | DWORD indefiniteNestingLevels = 0, decoded = 0; | |
1919 | ||
1920 | TRACE("(%p, %d)\n", pbEncoded, cbEncoded); | |
1921 | ||
1922 | do { | |
1923 | DWORD dataLen; | |
1924 | ||
1925 | if (!cbEncoded) | |
1926 | done = TRUE; | |
1927 | else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, | |
1928 | &dataLen))) | |
1929 | { | |
1930 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
1931 | ||
1932 | if (dataLen == CMSG_INDEFINITE_LENGTH) | |
1933 | { | |
1934 | indefiniteNestingLevels++; | |
1935 | pbEncoded += 1 + lenBytes; | |
1936 | cbEncoded -= 1 + lenBytes; | |
1937 | decoded += 1 + lenBytes; | |
1938 | TRACE("indefiniteNestingLevels = %d\n", | |
1939 | indefiniteNestingLevels); | |
1940 | } | |
1941 | else | |
1942 | { | |
1943 | if (pbEncoded[0] == 0 && pbEncoded[1] == 0 && | |
1944 | indefiniteNestingLevels) | |
1945 | { | |
1946 | indefiniteNestingLevels--; | |
1947 | TRACE("indefiniteNestingLevels = %d\n", | |
1948 | indefiniteNestingLevels); | |
1949 | } | |
1950 | pbEncoded += 1 + lenBytes + dataLen; | |
1951 | cbEncoded -= 1 + lenBytes + dataLen; | |
1952 | decoded += 1 + lenBytes + dataLen; | |
1953 | if (!indefiniteNestingLevels) | |
1954 | done = TRUE; | |
1955 | } | |
1956 | } | |
1957 | } while (ret && !done); | |
1958 | /* If we haven't found all 0 TLVs, we haven't found the end */ | |
1959 | if (ret && indefiniteNestingLevels) | |
1960 | { | |
1961 | SetLastError(CRYPT_E_ASN1_EOD); | |
1962 | ret = FALSE; | |
1963 | } | |
1964 | if (ret) | |
1965 | *pcbDecoded = decoded; | |
1966 | TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0); | |
1967 | return ret; | |
1968 | } | |
1969 | ||
e03864a2 | 1970 | static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded, |
731d37b0 JL |
1971 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, |
1972 | DWORD *pcbDecoded) | |
f224b34e JL |
1973 | { |
1974 | BOOL ret = TRUE; | |
9c4c856f | 1975 | DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0; |
f224b34e | 1976 | |
731d37b0 JL |
1977 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
1978 | pvStructInfo, *pcbStructInfo); | |
f224b34e | 1979 | |
9c4c856f | 1980 | if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen))) |
f224b34e | 1981 | { |
9c4c856f JL |
1982 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) |
1983 | bytesNeeded += encodedLen; | |
1984 | if (!pvStructInfo) | |
1985 | *pcbStructInfo = bytesNeeded; | |
1986 | else if (*pcbStructInfo < bytesNeeded) | |
1987 | { | |
1988 | SetLastError(ERROR_MORE_DATA); | |
1989 | *pcbStructInfo = bytesNeeded; | |
1990 | ret = FALSE; | |
1991 | } | |
f224b34e JL |
1992 | else |
1993 | { | |
9c4c856f JL |
1994 | PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo; |
1995 | ||
1996 | *pcbStructInfo = bytesNeeded; | |
1997 | blob->cbData = encodedLen; | |
1998 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) | |
1999 | blob->pbData = (LPBYTE)pbEncoded; | |
2000 | else | |
2001 | { | |
2002 | assert(blob->pbData); | |
2003 | memcpy(blob->pbData, pbEncoded, blob->cbData); | |
2004 | } | |
f224b34e | 2005 | } |
9c4c856f JL |
2006 | if (pcbDecoded) |
2007 | *pcbDecoded = encodedLen; | |
f224b34e JL |
2008 | } |
2009 | return ret; | |
2010 | } | |
2011 | ||
e03864a2 JL |
2012 | static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded, |
2013 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
97f2c658 JL |
2014 | { |
2015 | BOOL ret; | |
e03864a2 | 2016 | struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes, |
5674ca2e | 2017 | sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) }; |
97f2c658 JL |
2018 | struct GenericArray *array = (struct GenericArray *)pvStructInfo; |
2019 | ||
e03864a2 JL |
2020 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2021 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
97f2c658 JL |
2022 | |
2023 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 2024 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
b2f02f3b | 2025 | array ? array->rgItems : NULL); |
97f2c658 JL |
2026 | return ret; |
2027 | } | |
2028 | ||
731d37b0 JL |
2029 | static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded, |
2030 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2031 | DWORD *pcbDecoded) | |
2032 | { | |
2033 | BOOL ret; | |
2034 | struct AsnDecodeSequenceItem items[] = { | |
2035 | { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId), | |
e03864a2 | 2036 | CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, |
731d37b0 JL |
2037 | offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 }, |
2038 | { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue), | |
2039 | CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE, | |
2040 | offsetof(CRYPT_ATTRIBUTE, rgValue), 0 }, | |
2041 | }; | |
2042 | PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo; | |
2043 | ||
2044 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, | |
2045 | pvStructInfo, *pcbStructInfo); | |
2046 | ||
ce47433d JL |
2047 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2048 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, | |
2049 | pcbDecoded, attr ? attr->pszObjId : NULL); | |
731d37b0 JL |
2050 | TRACE("returning %d\n", ret); |
2051 | return ret; | |
2052 | } | |
2053 | ||
97f2c658 JL |
2054 | static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType, |
2055 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2056 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2057 | { | |
2058 | BOOL ret = FALSE; | |
2059 | ||
731d37b0 JL |
2060 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
2061 | pDecodePara, pvStructInfo, *pcbStructInfo); | |
2062 | ||
97f2c658 JL |
2063 | __TRY |
2064 | { | |
731d37b0 | 2065 | DWORD bytesNeeded; |
97f2c658 | 2066 | |
731d37b0 JL |
2067 | ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded, |
2068 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); | |
2069 | if (ret) | |
2070 | { | |
2071 | if (!pvStructInfo) | |
2072 | *pcbStructInfo = bytesNeeded; | |
2073 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
2074 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
2075 | { | |
2076 | PCRYPT_ATTRIBUTE attr; | |
2077 | ||
2078 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
2079 | pvStructInfo = *(BYTE **)pvStructInfo; | |
2080 | attr = (PCRYPT_ATTRIBUTE)pvStructInfo; | |
2081 | attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo + | |
2082 | sizeof(CRYPT_ATTRIBUTE)); | |
2083 | ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded, | |
2084 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded, | |
2085 | NULL); | |
2086 | } | |
2087 | } | |
e1f83a7a JL |
2088 | } |
2089 | __EXCEPT_PAGE_FAULT | |
2090 | { | |
2091 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2092 | } | |
2093 | __ENDTRY | |
2094 | TRACE("returning %d\n", ret); | |
2095 | return ret; | |
2096 | } | |
2097 | ||
e03864a2 JL |
2098 | static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded, |
2099 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2100 | DWORD *pcbDecoded) | |
e1f83a7a | 2101 | { |
731d37b0 JL |
2102 | struct AsnArrayDescriptor arrayDesc = { 0, |
2103 | CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE, | |
2104 | offsetof(CRYPT_ATTRIBUTE, pszObjId) }; | |
e1f83a7a JL |
2105 | PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo; |
2106 | BOOL ret; | |
2107 | ||
2108 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 2109 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr : |
e1f83a7a JL |
2110 | NULL); |
2111 | return ret; | |
2112 | } | |
2113 | ||
2114 | static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType, | |
2115 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2116 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2117 | { | |
2118 | BOOL ret = FALSE; | |
2119 | ||
2120 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, | |
2121 | pDecodePara, pvStructInfo, *pcbStructInfo); | |
2122 | ||
2123 | __TRY | |
2124 | { | |
2125 | DWORD bytesNeeded; | |
2126 | ||
c58cb379 JL |
2127 | if (!cbEncoded) |
2128 | SetLastError(CRYPT_E_ASN1_EOD); | |
2129 | else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF)) | |
2130 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
e03864a2 JL |
2131 | else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded, |
2132 | cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, | |
2133 | NULL))) | |
e1f83a7a JL |
2134 | { |
2135 | if (!pvStructInfo) | |
2136 | *pcbStructInfo = bytesNeeded; | |
2137 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
2138 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
2139 | { | |
2140 | PCRYPT_ATTRIBUTES attrs; | |
2141 | ||
2142 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
2143 | pvStructInfo = *(BYTE **)pvStructInfo; | |
2144 | attrs = (PCRYPT_ATTRIBUTES)pvStructInfo; | |
2145 | attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo + | |
2146 | sizeof(CRYPT_ATTRIBUTES)); | |
e03864a2 JL |
2147 | ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded, |
2148 | cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
2149 | &bytesNeeded, NULL); | |
e1f83a7a JL |
2150 | } |
2151 | } | |
97f2c658 JL |
2152 | } |
2153 | __EXCEPT_PAGE_FAULT | |
2154 | { | |
2155 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2156 | } | |
2157 | __ENDTRY | |
e1f83a7a | 2158 | TRACE("returning %d\n", ret); |
97f2c658 JL |
2159 | return ret; |
2160 | } | |
2161 | ||
e03864a2 JL |
2162 | static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded, |
2163 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
2164 | { |
2165 | CRYPT_ALGORITHM_IDENTIFIER *algo = | |
2166 | (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo; | |
2167 | BOOL ret = TRUE; | |
2168 | struct AsnDecodeSequenceItem items[] = { | |
2169 | { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), | |
e03864a2 | 2170 | CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, |
f224b34e JL |
2171 | offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 }, |
2172 | { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters), | |
2173 | CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, | |
2174 | offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 }, | |
2175 | }; | |
2176 | ||
e03864a2 JL |
2177 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2178 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e | 2179 | |
ce47433d | 2180 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
e03864a2 JL |
2181 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, |
2182 | pcbDecoded, algo ? algo->pszObjId : NULL); | |
f224b34e JL |
2183 | if (ret && pvStructInfo) |
2184 | { | |
2185 | TRACE("pszObjId is %p (%s)\n", algo->pszObjId, | |
2186 | debugstr_a(algo->pszObjId)); | |
2187 | } | |
2188 | return ret; | |
2189 | } | |
2190 | ||
e03864a2 JL |
2191 | static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded, |
2192 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2193 | DWORD *pcbDecoded) | |
f224b34e JL |
2194 | { |
2195 | BOOL ret = TRUE; | |
2196 | struct AsnDecodeSequenceItem items[] = { | |
2197 | { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm), | |
2198 | CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), | |
2199 | FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO, | |
2200 | Algorithm.pszObjId) }, | |
2201 | { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey), | |
2202 | CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, | |
2203 | offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) }, | |
2204 | }; | |
2205 | PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo; | |
2206 | ||
ce47433d | 2207 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
e03864a2 JL |
2208 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, |
2209 | pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL); | |
f224b34e JL |
2210 | return ret; |
2211 | } | |
2212 | ||
2213 | static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType, | |
2214 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2215 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2216 | { | |
2217 | BOOL ret = TRUE; | |
2218 | ||
2219 | __TRY | |
2220 | { | |
2221 | DWORD bytesNeeded; | |
2222 | ||
e03864a2 JL |
2223 | if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded, |
2224 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) | |
f224b34e JL |
2225 | { |
2226 | if (!pvStructInfo) | |
2227 | *pcbStructInfo = bytesNeeded; | |
2228 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
2229 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
2230 | { | |
2231 | PCERT_PUBLIC_KEY_INFO info; | |
2232 | ||
2233 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
2234 | pvStructInfo = *(BYTE **)pvStructInfo; | |
2235 | info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo; | |
2236 | info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo + | |
2237 | sizeof(CERT_PUBLIC_KEY_INFO); | |
e03864a2 JL |
2238 | ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded, |
2239 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
2240 | &bytesNeeded, NULL); | |
f224b34e JL |
2241 | } |
2242 | } | |
2243 | } | |
2244 | __EXCEPT_PAGE_FAULT | |
2245 | { | |
2246 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2247 | ret = FALSE; | |
2248 | } | |
2249 | __ENDTRY | |
2250 | return ret; | |
2251 | } | |
2252 | ||
e03864a2 JL |
2253 | static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded, |
2254 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
2255 | { |
2256 | BOOL ret; | |
2257 | ||
2258 | if (cbEncoded < 3) | |
2259 | { | |
2260 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2261 | return FALSE; | |
2262 | } | |
2263 | if (GET_LEN_BYTES(pbEncoded[1]) > 1) | |
2264 | { | |
2265 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2266 | return FALSE; | |
2267 | } | |
2268 | if (pbEncoded[1] > 1) | |
2269 | { | |
2270 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2271 | return FALSE; | |
2272 | } | |
2e8ae598 JL |
2273 | if (pcbDecoded) |
2274 | *pcbDecoded = 3; | |
f224b34e JL |
2275 | if (!pvStructInfo) |
2276 | { | |
2277 | *pcbStructInfo = sizeof(BOOL); | |
2278 | ret = TRUE; | |
2279 | } | |
2280 | else if (*pcbStructInfo < sizeof(BOOL)) | |
2281 | { | |
2282 | *pcbStructInfo = sizeof(BOOL); | |
2283 | SetLastError(ERROR_MORE_DATA); | |
2284 | ret = FALSE; | |
2285 | } | |
2286 | else | |
2287 | { | |
2288 | *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE; | |
2289 | ret = TRUE; | |
2290 | } | |
f3a1f2bf | 2291 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
2292 | return ret; |
2293 | } | |
2294 | ||
731d37b0 JL |
2295 | static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded, |
2296 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
2297 | { |
2298 | PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo; | |
2299 | DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY); | |
2300 | BOOL ret; | |
2301 | ||
731d37b0 JL |
2302 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
2303 | pvStructInfo, *pcbStructInfo); | |
f224b34e JL |
2304 | |
2305 | if (cbEncoded < 2) | |
2306 | { | |
2307 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2308 | return FALSE; | |
2309 | } | |
f224b34e JL |
2310 | lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
2311 | if (1 + lenBytes > cbEncoded) | |
2312 | { | |
2313 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2314 | return FALSE; | |
2315 | } | |
2316 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
2317 | { | |
2318 | switch (pbEncoded[0] & ASN_TYPE_MASK) | |
2319 | { | |
2320 | case 1: /* rfc822Name */ | |
2321 | case 2: /* dNSName */ | |
2322 | case 6: /* uniformResourceIdentifier */ | |
2323 | bytesNeeded += (dataLen + 1) * sizeof(WCHAR); | |
2324 | break; | |
44948c3b | 2325 | case 4: /* directoryName */ |
f224b34e JL |
2326 | case 7: /* iPAddress */ |
2327 | bytesNeeded += dataLen; | |
2328 | break; | |
2329 | case 8: /* registeredID */ | |
1dd1c6c2 JL |
2330 | ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL, |
2331 | &dataLen, NULL); | |
44948c3b JL |
2332 | if (ret) |
2333 | { | |
2334 | /* FIXME: ugly, shouldn't need to know internals of OID decode | |
2335 | * function to use it. | |
2336 | */ | |
2337 | bytesNeeded += dataLen - sizeof(LPSTR); | |
2338 | } | |
2339 | break; | |
f224b34e | 2340 | case 0: /* otherName */ |
0cb61484 | 2341 | FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK); |
f224b34e JL |
2342 | SetLastError(CRYPT_E_ASN1_BADTAG); |
2343 | ret = FALSE; | |
2344 | break; | |
2345 | case 3: /* x400Address, unimplemented */ | |
2346 | case 5: /* ediPartyName, unimplemented */ | |
0cb61484 | 2347 | TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK); |
f224b34e JL |
2348 | SetLastError(CRYPT_E_ASN1_BADTAG); |
2349 | ret = FALSE; | |
2350 | break; | |
2351 | default: | |
0cb61484 | 2352 | TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK); |
f224b34e JL |
2353 | SetLastError(CRYPT_E_ASN1_CORRUPT); |
2354 | ret = FALSE; | |
2355 | } | |
2356 | if (ret) | |
2357 | { | |
1f4bcb4a JL |
2358 | if (pcbDecoded) |
2359 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
2360 | if (!entry) |
2361 | *pcbStructInfo = bytesNeeded; | |
2362 | else if (*pcbStructInfo < bytesNeeded) | |
2363 | { | |
2364 | *pcbStructInfo = bytesNeeded; | |
2365 | SetLastError(ERROR_MORE_DATA); | |
2366 | ret = FALSE; | |
2367 | } | |
2368 | else | |
2369 | { | |
2370 | *pcbStructInfo = bytesNeeded; | |
2371 | /* MS used values one greater than the asn1 ones.. sigh */ | |
2372 | entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1; | |
2373 | switch (pbEncoded[0] & ASN_TYPE_MASK) | |
2374 | { | |
2375 | case 1: /* rfc822Name */ | |
2376 | case 2: /* dNSName */ | |
2377 | case 6: /* uniformResourceIdentifier */ | |
2378 | { | |
2379 | DWORD i; | |
2380 | ||
2381 | for (i = 0; i < dataLen; i++) | |
2382 | entry->u.pwszURL[i] = | |
2383 | (WCHAR)pbEncoded[1 + lenBytes + i]; | |
2384 | entry->u.pwszURL[i] = 0; | |
2385 | TRACE("URL is %p (%s)\n", entry->u.pwszURL, | |
2386 | debugstr_w(entry->u.pwszURL)); | |
2387 | break; | |
2388 | } | |
44948c3b JL |
2389 | case 4: /* directoryName */ |
2390 | entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME; | |
2391 | /* The data are memory-equivalent with the IPAddress case, | |
2392 | * fall-through | |
2393 | */ | |
f224b34e JL |
2394 | case 7: /* iPAddress */ |
2395 | /* The next data pointer is in the pwszURL spot, that is, | |
2396 | * the first 4 bytes. Need to move it to the next spot. | |
2397 | */ | |
2398 | entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL; | |
2399 | entry->u.IPAddress.cbData = dataLen; | |
2400 | memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes, | |
2401 | dataLen); | |
2402 | break; | |
44948c3b | 2403 | case 8: /* registeredID */ |
1dd1c6c2 JL |
2404 | ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, |
2405 | &entry->u.pszRegisteredID, &dataLen, NULL); | |
44948c3b | 2406 | break; |
f224b34e JL |
2407 | } |
2408 | } | |
2409 | } | |
2410 | } | |
2411 | return ret; | |
2412 | } | |
2413 | ||
e03864a2 JL |
2414 | static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded, |
2415 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2416 | DWORD *pcbDecoded) | |
f224b34e JL |
2417 | { |
2418 | BOOL ret = TRUE; | |
2d00a4f0 | 2419 | struct AsnArrayDescriptor arrayDesc = { 0, |
f224b34e JL |
2420 | CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, |
2421 | offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) }; | |
2422 | PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo; | |
2423 | ||
e03864a2 JL |
2424 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2425 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
2426 | |
2427 | if (info) | |
2428 | TRACE("info->rgAltEntry is %p\n", info->rgAltEntry); | |
2429 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 2430 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
b2f02f3b | 2431 | info ? info->rgAltEntry : NULL); |
f224b34e JL |
2432 | return ret; |
2433 | } | |
2434 | ||
b82bfa34 | 2435 | /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */ |
e03864a2 JL |
2436 | static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded, |
2437 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2438 | DWORD *pcbDecoded) | |
b82bfa34 JL |
2439 | { |
2440 | BOOL ret; | |
2441 | ||
e03864a2 JL |
2442 | TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags, |
2443 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
b82bfa34 JL |
2444 | |
2445 | /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in- | |
2446 | * place. | |
2447 | */ | |
e03864a2 JL |
2448 | ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, |
2449 | dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo, | |
2450 | pcbDecoded); | |
b82bfa34 JL |
2451 | if (ret && pvStructInfo) |
2452 | { | |
2453 | CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo; | |
2454 | ||
2455 | if (blob->cbData) | |
2456 | { | |
2457 | DWORD i; | |
2458 | BYTE temp; | |
2459 | ||
2460 | for (i = 0; i < blob->cbData / 2; i++) | |
2461 | { | |
2462 | temp = blob->pbData[i]; | |
2463 | blob->pbData[i] = blob->pbData[blob->cbData - i - 1]; | |
2464 | blob->pbData[blob->cbData - i - 1] = temp; | |
2465 | } | |
2466 | } | |
2467 | } | |
2468 | TRACE("returning %d (%08x)\n", ret, GetLastError()); | |
2469 | return ret; | |
2470 | } | |
2471 | ||
9153d39c JL |
2472 | static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType, |
2473 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2474 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2475 | { | |
2476 | BOOL ret; | |
2477 | ||
2478 | __TRY | |
2479 | { | |
2480 | struct AsnDecodeSequenceItem items[] = { | |
2481 | { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId), | |
b82bfa34 | 2482 | CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB), |
9153d39c JL |
2483 | TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 }, |
2484 | { ASN_CONTEXT | ASN_CONSTRUCTOR| 1, | |
2485 | offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer), | |
2486 | CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE, | |
2487 | offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 }, | |
2488 | { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO, | |
2489 | CertSerialNumber), CRYPT_AsnDecodeIntegerInternal, | |
2490 | sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE, | |
2491 | offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 }, | |
2492 | }; | |
2493 | ||
ce47433d JL |
2494 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2495 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
2496 | pcbStructInfo, NULL, NULL); | |
9153d39c JL |
2497 | } |
2498 | __EXCEPT_PAGE_FAULT | |
2499 | { | |
2500 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2501 | ret = FALSE; | |
2502 | } | |
2503 | __ENDTRY | |
2504 | return ret; | |
2505 | } | |
2506 | ||
2d00a4f0 JL |
2507 | static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType, |
2508 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2509 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2510 | { | |
2511 | BOOL ret; | |
2512 | ||
2513 | __TRY | |
2514 | { | |
2515 | struct AsnDecodeSequenceItem items[] = { | |
2516 | { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId), | |
b82bfa34 | 2517 | CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB), |
2d00a4f0 JL |
2518 | TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 }, |
2519 | { ASN_CONTEXT | ASN_CONSTRUCTOR| 1, | |
2520 | offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer), | |
2521 | CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, | |
2522 | TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, | |
2523 | AuthorityCertIssuer.rgAltEntry), 0 }, | |
2524 | { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, | |
2525 | AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal, | |
2526 | sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE, | |
2527 | offsetof(CERT_AUTHORITY_KEY_ID2_INFO, | |
2528 | AuthorityCertSerialNumber.pbData), 0 }, | |
2529 | }; | |
2530 | ||
ce47433d JL |
2531 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2532 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
2533 | pcbStructInfo, NULL, NULL); | |
2d00a4f0 JL |
2534 | } |
2535 | __EXCEPT_PAGE_FAULT | |
2536 | { | |
2537 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2538 | ret = FALSE; | |
2539 | } | |
2540 | __ENDTRY | |
2541 | return ret; | |
2542 | } | |
2543 | ||
e03864a2 JL |
2544 | static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded, |
2545 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
1cd9510b JL |
2546 | { |
2547 | BOOL ret; | |
2548 | DWORD dataLen; | |
2549 | ||
e03864a2 JL |
2550 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2551 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
1cd9510b JL |
2552 | |
2553 | /* The caller has already checked the tag, no need to check it again. | |
7e475b4a | 2554 | * Check the outer length is valid: |
1cd9510b | 2555 | */ |
7e475b4a | 2556 | if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen))) |
1cd9510b JL |
2557 | { |
2558 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
2559 | DWORD innerLen; | |
2560 | ||
2561 | pbEncoded += 1 + lenBytes; | |
7e475b4a JL |
2562 | cbEncoded -= 1 + lenBytes; |
2563 | if (dataLen == CMSG_INDEFINITE_LENGTH) | |
2564 | cbEncoded -= 2; /* space for 0 TLV */ | |
2565 | /* Check the inner length is valid: */ | |
2566 | if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen))) | |
1cd9510b | 2567 | { |
7e475b4a JL |
2568 | DWORD decodedLen; |
2569 | ||
2570 | ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, | |
2571 | pvStructInfo, pcbStructInfo, &decodedLen); | |
2572 | if (dataLen == CMSG_INDEFINITE_LENGTH) | |
2573 | { | |
2574 | if (*(pbEncoded + decodedLen) != 0 || | |
2575 | *(pbEncoded + decodedLen + 1) != 0) | |
2576 | { | |
2577 | TRACE("expected 0 TLV, got {%02x,%02x}\n", | |
2578 | *(pbEncoded + decodedLen), | |
2579 | *(pbEncoded + decodedLen + 1)); | |
2580 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2581 | ret = FALSE; | |
2582 | } | |
2583 | else | |
2584 | decodedLen += 2; | |
2585 | } | |
2586 | if (ret && pcbDecoded) | |
2587 | { | |
2588 | *pcbDecoded = 1 + lenBytes + decodedLen; | |
2589 | TRACE("decoded %d bytes\n", *pcbDecoded); | |
2590 | } | |
1cd9510b JL |
2591 | } |
2592 | } | |
2593 | return ret; | |
2594 | } | |
2595 | ||
e03864a2 JL |
2596 | static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded, |
2597 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2598 | DWORD *pcbDecoded) | |
35abf3ad JL |
2599 | { |
2600 | CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo; | |
2601 | struct AsnDecodeSequenceItem items[] = { | |
2602 | { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId), | |
e03864a2 | 2603 | CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, |
35abf3ad JL |
2604 | offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 }, |
2605 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, | |
2606 | offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent, | |
2607 | sizeof(CRYPT_DER_BLOB), TRUE, TRUE, | |
2608 | offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 }, | |
2609 | }; | |
a50d8dc1 JL |
2610 | BOOL ret; |
2611 | ||
e03864a2 JL |
2612 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2613 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
35abf3ad | 2614 | |
ce47433d | 2615 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
e03864a2 JL |
2616 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, |
2617 | pcbDecoded, info ? info->pszObjId : NULL); | |
a50d8dc1 | 2618 | return ret; |
35abf3ad JL |
2619 | } |
2620 | ||
1cd9510b JL |
2621 | static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType, |
2622 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2623 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2624 | { | |
2625 | BOOL ret = FALSE; | |
2626 | ||
2627 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, | |
2628 | pDecodePara, pvStructInfo, *pcbStructInfo); | |
2629 | ||
2630 | __TRY | |
2631 | { | |
e03864a2 JL |
2632 | ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded, |
2633 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); | |
35abf3ad JL |
2634 | if (ret && pvStructInfo) |
2635 | { | |
2636 | ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, | |
2637 | pcbStructInfo, *pcbStructInfo); | |
2638 | if (ret) | |
2639 | { | |
2640 | CRYPT_CONTENT_INFO *info; | |
1cd9510b | 2641 | |
35abf3ad JL |
2642 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) |
2643 | pvStructInfo = *(BYTE **)pvStructInfo; | |
2644 | info = (CRYPT_CONTENT_INFO *)pvStructInfo; | |
2645 | info->pszObjId = (LPSTR)((BYTE *)info + | |
2646 | sizeof(CRYPT_CONTENT_INFO)); | |
e03864a2 JL |
2647 | ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, |
2648 | cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
2649 | pcbStructInfo, NULL); | |
35abf3ad JL |
2650 | } |
2651 | } | |
1cd9510b JL |
2652 | } |
2653 | __EXCEPT_PAGE_FAULT | |
2654 | { | |
2655 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2656 | } | |
2657 | __ENDTRY | |
2658 | return ret; | |
1cd9510b JL |
2659 | } |
2660 | ||
35abf3ad JL |
2661 | BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded, |
2662 | DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, | |
2663 | CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData) | |
2664 | { | |
2665 | BOOL ret; | |
2666 | struct AsnDecodeSequenceItem items[] = { | |
89a541a4 JL |
2667 | { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), |
2668 | CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, | |
35abf3ad JL |
2669 | { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm), |
2670 | CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), | |
2671 | FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId), | |
2672 | 0 }, | |
2673 | { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo), | |
2674 | CRYPT_AsnDecodePKCSContentInfoInternal, | |
2675 | sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, | |
2676 | ContentInfo.pszObjId), 0 }, | |
2677 | { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash), | |
2678 | CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE, | |
2679 | offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 }, | |
2680 | }; | |
2681 | ||
ce47433d JL |
2682 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2683 | pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData, | |
2684 | NULL, NULL); | |
35abf3ad JL |
2685 | return ret; |
2686 | } | |
2687 | ||
f224b34e JL |
2688 | static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType, |
2689 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2690 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2691 | { | |
2692 | BOOL ret = TRUE; | |
2693 | ||
f3a1f2bf | 2694 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
2695 | pDecodePara, pvStructInfo, *pcbStructInfo); |
2696 | ||
2697 | __TRY | |
2698 | { | |
ad949822 | 2699 | DWORD bytesNeeded; |
f224b34e | 2700 | |
e03864a2 JL |
2701 | if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded, |
2702 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) | |
ad949822 JL |
2703 | { |
2704 | if (!pvStructInfo) | |
2705 | *pcbStructInfo = bytesNeeded; | |
2706 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
2707 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
2708 | { | |
2709 | CERT_ALT_NAME_INFO *name; | |
2710 | ||
2711 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
2712 | pvStructInfo = *(BYTE **)pvStructInfo; | |
2713 | name = (CERT_ALT_NAME_INFO *)pvStructInfo; | |
2714 | name->rgAltEntry = (PCERT_ALT_NAME_ENTRY) | |
2715 | ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO)); | |
e03864a2 JL |
2716 | ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded, |
2717 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
2718 | &bytesNeeded, NULL); | |
ad949822 JL |
2719 | } |
2720 | } | |
f224b34e JL |
2721 | } |
2722 | __EXCEPT_PAGE_FAULT | |
2723 | { | |
2724 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2725 | ret = FALSE; | |
2726 | } | |
2727 | __ENDTRY | |
2728 | return ret; | |
2729 | } | |
2730 | ||
2731 | struct PATH_LEN_CONSTRAINT | |
2732 | { | |
2733 | BOOL fPathLenConstraint; | |
2734 | DWORD dwPathLenConstraint; | |
2735 | }; | |
2736 | ||
e03864a2 JL |
2737 | static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded, |
2738 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2739 | DWORD *pcbDecoded) | |
f224b34e JL |
2740 | { |
2741 | BOOL ret = TRUE; | |
be91ad36 | 2742 | DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size; |
f224b34e | 2743 | |
e03864a2 JL |
2744 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2745 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e | 2746 | |
be91ad36 | 2747 | if (!pvStructInfo) |
f224b34e | 2748 | { |
be91ad36 JL |
2749 | ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL, |
2750 | &size, pcbDecoded); | |
2751 | *pcbStructInfo = bytesNeeded; | |
2752 | } | |
2753 | else if (*pcbStructInfo < bytesNeeded) | |
2754 | { | |
2755 | SetLastError(ERROR_MORE_DATA); | |
2756 | *pcbStructInfo = bytesNeeded; | |
2757 | ret = FALSE; | |
2758 | } | |
2759 | else | |
2760 | { | |
2761 | struct PATH_LEN_CONSTRAINT *constraint = | |
2762 | (struct PATH_LEN_CONSTRAINT *)pvStructInfo; | |
f224b34e | 2763 | |
be91ad36 JL |
2764 | size = sizeof(constraint->dwPathLenConstraint); |
2765 | ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, | |
2766 | &constraint->dwPathLenConstraint, &size, pcbDecoded); | |
2767 | if (ret) | |
2768 | constraint->fPathLenConstraint = TRUE; | |
2769 | TRACE("got an int, dwPathLenConstraint is %d\n", | |
2770 | constraint->dwPathLenConstraint); | |
f224b34e | 2771 | } |
f3a1f2bf | 2772 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
2773 | return ret; |
2774 | } | |
2775 | ||
e03864a2 JL |
2776 | static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded, |
2777 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2778 | DWORD *pcbDecoded) | |
f224b34e JL |
2779 | { |
2780 | BOOL ret; | |
2781 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
e03864a2 | 2782 | CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE, |
f224b34e JL |
2783 | offsetof(CERT_NAME_BLOB, pbData) }; |
2784 | struct GenericArray *entries = (struct GenericArray *)pvStructInfo; | |
2785 | ||
e03864a2 JL |
2786 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2787 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
2788 | |
2789 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 2790 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
f224b34e | 2791 | entries ? entries->rgItems : NULL); |
f3a1f2bf | 2792 | TRACE("Returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
2793 | return ret; |
2794 | } | |
2795 | ||
2796 | static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType, | |
2797 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2798 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2799 | { | |
2800 | BOOL ret; | |
2801 | ||
2802 | __TRY | |
2803 | { | |
2804 | struct AsnDecodeSequenceItem items[] = { | |
2805 | { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType), | |
2806 | CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, | |
2807 | offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 }, | |
2808 | { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO, | |
2809 | fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint, | |
2810 | sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 }, | |
2811 | { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO, | |
2812 | cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints, | |
2813 | sizeof(struct GenericArray), TRUE, TRUE, | |
2814 | offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 }, | |
2815 | }; | |
2816 | ||
ce47433d JL |
2817 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2818 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
2819 | pcbStructInfo, NULL, NULL); | |
f224b34e JL |
2820 | } |
2821 | __EXCEPT_PAGE_FAULT | |
2822 | { | |
2823 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2824 | ret = FALSE; | |
2825 | } | |
2826 | __ENDTRY | |
2827 | return ret; | |
2828 | } | |
2829 | ||
2830 | static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType, | |
2831 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2832 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2833 | { | |
2834 | BOOL ret; | |
2835 | ||
2836 | __TRY | |
2837 | { | |
2838 | struct AsnDecodeSequenceItem items[] = { | |
2839 | { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), | |
2840 | CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 }, | |
2841 | { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, | |
2842 | fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint, | |
2843 | sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 }, | |
2844 | }; | |
2845 | ||
ce47433d JL |
2846 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2847 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
2848 | pcbStructInfo, NULL, NULL); | |
f224b34e JL |
2849 | } |
2850 | __EXCEPT_PAGE_FAULT | |
2851 | { | |
2852 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2853 | ret = FALSE; | |
2854 | } | |
2855 | __ENDTRY | |
2856 | return ret; | |
2857 | } | |
2858 | ||
2859 | #define RSA1_MAGIC 0x31415352 | |
2860 | ||
2861 | struct DECODED_RSA_PUB_KEY | |
2862 | { | |
2863 | DWORD pubexp; | |
2864 | CRYPT_INTEGER_BLOB modulus; | |
2865 | }; | |
2866 | ||
2867 | static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType, | |
2868 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2869 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2870 | { | |
2871 | BOOL ret; | |
2872 | ||
2873 | __TRY | |
2874 | { | |
2875 | struct AsnDecodeSequenceItem items[] = { | |
2876 | { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus), | |
2877 | CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), | |
2878 | FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData), | |
2879 | 0 }, | |
2880 | { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp), | |
89a541a4 | 2881 | CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, |
f224b34e JL |
2882 | }; |
2883 | struct DECODED_RSA_PUB_KEY *decodedKey = NULL; | |
2884 | DWORD size = 0; | |
2885 | ||
ce47433d JL |
2886 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
2887 | pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, | |
2888 | &size, NULL, NULL); | |
f224b34e JL |
2889 | if (ret) |
2890 | { | |
2891 | DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + | |
2892 | decodedKey->modulus.cbData; | |
2893 | ||
2894 | if (!pvStructInfo) | |
2895 | { | |
2896 | *pcbStructInfo = bytesNeeded; | |
2897 | ret = TRUE; | |
2898 | } | |
2899 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
2900 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
2901 | { | |
2902 | BLOBHEADER *hdr; | |
2903 | RSAPUBKEY *rsaPubKey; | |
2904 | ||
2905 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
2906 | pvStructInfo = *(BYTE **)pvStructInfo; | |
2907 | hdr = (BLOBHEADER *)pvStructInfo; | |
2908 | hdr->bType = PUBLICKEYBLOB; | |
2909 | hdr->bVersion = CUR_BLOB_VERSION; | |
2910 | hdr->reserved = 0; | |
2911 | hdr->aiKeyAlg = CALG_RSA_KEYX; | |
2912 | rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo + | |
2913 | sizeof(BLOBHEADER)); | |
2914 | rsaPubKey->magic = RSA1_MAGIC; | |
2915 | rsaPubKey->pubexp = decodedKey->pubexp; | |
2916 | rsaPubKey->bitlen = decodedKey->modulus.cbData * 8; | |
2917 | memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) + | |
2918 | sizeof(RSAPUBKEY), decodedKey->modulus.pbData, | |
2919 | decodedKey->modulus.cbData); | |
2920 | } | |
2921 | LocalFree(decodedKey); | |
2922 | } | |
2923 | } | |
2924 | __EXCEPT_PAGE_FAULT | |
2925 | { | |
2926 | SetLastError(STATUS_ACCESS_VIOLATION); | |
2927 | ret = FALSE; | |
2928 | } | |
2929 | __ENDTRY | |
2930 | return ret; | |
2931 | } | |
2932 | ||
e03864a2 JL |
2933 | static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded, |
2934 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
2935 | DWORD *pcbDecoded) | |
f224b34e JL |
2936 | { |
2937 | BOOL ret; | |
2938 | DWORD bytesNeeded, dataLen; | |
2939 | ||
e03864a2 JL |
2940 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
2941 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
2942 | |
2943 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
2944 | { | |
2e8ae598 JL |
2945 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
2946 | ||
f224b34e JL |
2947 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) |
2948 | bytesNeeded = sizeof(CRYPT_DATA_BLOB); | |
2949 | else | |
2950 | bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB); | |
2e8ae598 JL |
2951 | if (pcbDecoded) |
2952 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
2953 | if (!pvStructInfo) |
2954 | *pcbStructInfo = bytesNeeded; | |
2955 | else if (*pcbStructInfo < bytesNeeded) | |
2956 | { | |
2957 | SetLastError(ERROR_MORE_DATA); | |
2958 | *pcbStructInfo = bytesNeeded; | |
2959 | ret = FALSE; | |
2960 | } | |
2961 | else | |
2962 | { | |
2963 | CRYPT_DATA_BLOB *blob; | |
f224b34e JL |
2964 | |
2965 | blob = (CRYPT_DATA_BLOB *)pvStructInfo; | |
2966 | blob->cbData = dataLen; | |
2967 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) | |
2968 | blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes; | |
2969 | else | |
2970 | { | |
2971 | assert(blob->pbData); | |
2972 | if (blob->cbData) | |
2973 | memcpy(blob->pbData, pbEncoded + 1 + lenBytes, | |
2974 | blob->cbData); | |
2975 | } | |
2976 | } | |
2977 | } | |
2978 | return ret; | |
2979 | } | |
2980 | ||
2981 | static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType, | |
2982 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
2983 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
2984 | { | |
2985 | BOOL ret; | |
2986 | ||
f3a1f2bf | 2987 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
2988 | pDecodePara, pvStructInfo, *pcbStructInfo); |
2989 | ||
2990 | __TRY | |
2991 | { | |
2992 | DWORD bytesNeeded; | |
2993 | ||
2994 | if (!cbEncoded) | |
2995 | { | |
2996 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
2997 | ret = FALSE; | |
2998 | } | |
2999 | else if (pbEncoded[0] != ASN_OCTETSTRING) | |
3000 | { | |
3001 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3002 | ret = FALSE; | |
3003 | } | |
e03864a2 JL |
3004 | else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, |
3005 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) | |
f224b34e JL |
3006 | { |
3007 | if (!pvStructInfo) | |
3008 | *pcbStructInfo = bytesNeeded; | |
3009 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3010 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3011 | { | |
3012 | CRYPT_DATA_BLOB *blob; | |
3013 | ||
3014 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3015 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3016 | blob = (CRYPT_DATA_BLOB *)pvStructInfo; | |
3017 | blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB); | |
e03864a2 JL |
3018 | ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, |
3019 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
3020 | &bytesNeeded, NULL); | |
f224b34e JL |
3021 | } |
3022 | } | |
3023 | } | |
3024 | __EXCEPT_PAGE_FAULT | |
3025 | { | |
3026 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3027 | ret = FALSE; | |
3028 | } | |
3029 | __ENDTRY | |
3030 | return ret; | |
3031 | } | |
3032 | ||
e03864a2 JL |
3033 | static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded, |
3034 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
3035 | { |
3036 | BOOL ret; | |
3037 | ||
e03864a2 JL |
3038 | TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags, |
3039 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
f224b34e JL |
3040 | |
3041 | if (pbEncoded[0] == ASN_BITSTRING) | |
3042 | { | |
3043 | DWORD bytesNeeded, dataLen; | |
2e8ae598 | 3044 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
f224b34e JL |
3045 | |
3046 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
3047 | { | |
3048 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) | |
3049 | bytesNeeded = sizeof(CRYPT_BIT_BLOB); | |
3050 | else | |
3051 | bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB); | |
2e8ae598 JL |
3052 | if (pcbDecoded) |
3053 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
3054 | if (!pvStructInfo) |
3055 | *pcbStructInfo = bytesNeeded; | |
3056 | else if (*pcbStructInfo < bytesNeeded) | |
3057 | { | |
3058 | *pcbStructInfo = bytesNeeded; | |
3059 | SetLastError(ERROR_MORE_DATA); | |
3060 | ret = FALSE; | |
3061 | } | |
3062 | else | |
3063 | { | |
3064 | CRYPT_BIT_BLOB *blob; | |
3065 | ||
3066 | blob = (CRYPT_BIT_BLOB *)pvStructInfo; | |
3067 | blob->cbData = dataLen - 1; | |
2e8ae598 | 3068 | blob->cUnusedBits = *(pbEncoded + 1 + lenBytes); |
f224b34e JL |
3069 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) |
3070 | { | |
2e8ae598 | 3071 | blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes; |
f224b34e JL |
3072 | } |
3073 | else | |
3074 | { | |
3075 | assert(blob->pbData); | |
3076 | if (blob->cbData) | |
3077 | { | |
3078 | BYTE mask = 0xff << blob->cUnusedBits; | |
3079 | ||
2e8ae598 JL |
3080 | memcpy(blob->pbData, pbEncoded + 2 + lenBytes, |
3081 | blob->cbData); | |
f224b34e JL |
3082 | blob->pbData[blob->cbData - 1] &= mask; |
3083 | } | |
3084 | } | |
3085 | } | |
3086 | } | |
3087 | } | |
3088 | else | |
3089 | { | |
3090 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3091 | ret = FALSE; | |
3092 | } | |
f3a1f2bf | 3093 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
3094 | return ret; |
3095 | } | |
3096 | ||
3097 | static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType, | |
3098 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3099 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3100 | { | |
3101 | BOOL ret; | |
3102 | ||
f3a1f2bf | 3103 | TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
3104 | pDecodePara, pvStructInfo, pcbStructInfo); |
3105 | ||
3106 | __TRY | |
3107 | { | |
3108 | DWORD bytesNeeded; | |
3109 | ||
e03864a2 JL |
3110 | if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, |
3111 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) | |
f224b34e JL |
3112 | { |
3113 | if (!pvStructInfo) | |
3114 | *pcbStructInfo = bytesNeeded; | |
3115 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3116 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3117 | { | |
3118 | CRYPT_BIT_BLOB *blob; | |
3119 | ||
3120 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3121 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3122 | blob = (CRYPT_BIT_BLOB *)pvStructInfo; | |
3123 | blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB); | |
e03864a2 JL |
3124 | ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, |
3125 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
3126 | &bytesNeeded, NULL); | |
f224b34e JL |
3127 | } |
3128 | } | |
3129 | } | |
3130 | __EXCEPT_PAGE_FAULT | |
3131 | { | |
3132 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3133 | ret = FALSE; | |
3134 | } | |
3135 | __ENDTRY | |
f3a1f2bf | 3136 | TRACE("returning %d (%08x)\n", ret, GetLastError()); |
f224b34e JL |
3137 | return ret; |
3138 | } | |
3139 | ||
30355fa6 | 3140 | /* Ignores tag. Only allows integers 4 bytes or smaller in size. */ |
e03864a2 JL |
3141 | static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded, |
3142 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
5fbca384 JL |
3143 | { |
3144 | BOOL ret; | |
3145 | BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)]; | |
3146 | CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf; | |
3147 | DWORD size = sizeof(buf); | |
3148 | ||
3149 | blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB); | |
30355fa6 JL |
3150 | ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf, |
3151 | &size, pcbDecoded); | |
5fbca384 JL |
3152 | if (ret) |
3153 | { | |
3154 | if (!pvStructInfo) | |
3155 | *pcbStructInfo = sizeof(int); | |
8c5bd5f5 | 3156 | else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int)))) |
5fbca384 JL |
3157 | { |
3158 | int val, i; | |
3159 | ||
3160 | if (blob->pbData[blob->cbData - 1] & 0x80) | |
3161 | { | |
3162 | /* initialize to a negative value to sign-extend */ | |
3163 | val = -1; | |
3164 | } | |
3165 | else | |
3166 | val = 0; | |
3167 | for (i = 0; i < blob->cbData; i++) | |
3168 | { | |
3169 | val <<= 8; | |
3170 | val |= blob->pbData[blob->cbData - i - 1]; | |
3171 | } | |
3172 | memcpy(pvStructInfo, &val, sizeof(int)); | |
3173 | } | |
3174 | } | |
3175 | else if (GetLastError() == ERROR_MORE_DATA) | |
3176 | SetLastError(CRYPT_E_ASN1_LARGE); | |
3177 | return ret; | |
3178 | } | |
3179 | ||
f224b34e JL |
3180 | static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, |
3181 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3182 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3183 | { | |
3184 | BOOL ret; | |
3185 | ||
f224b34e JL |
3186 | __TRY |
3187 | { | |
5fbca384 | 3188 | DWORD bytesNeeded; |
f224b34e | 3189 | |
30355fa6 JL |
3190 | if (!cbEncoded) |
3191 | { | |
3192 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
3193 | ret = FALSE; | |
3194 | } | |
3195 | else if (pbEncoded[0] != ASN_INTEGER) | |
3196 | { | |
3197 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3198 | ret = FALSE; | |
3199 | } | |
3200 | else | |
3201 | ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, | |
3202 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); | |
f224b34e JL |
3203 | if (ret) |
3204 | { | |
5fbca384 JL |
3205 | if (!pvStructInfo) |
3206 | *pcbStructInfo = bytesNeeded; | |
3207 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3208 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
f224b34e | 3209 | { |
f224b34e JL |
3210 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) |
3211 | pvStructInfo = *(BYTE **)pvStructInfo; | |
e03864a2 JL |
3212 | ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, |
3213 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
3214 | &bytesNeeded, NULL); | |
f224b34e JL |
3215 | } |
3216 | } | |
f224b34e JL |
3217 | } |
3218 | __EXCEPT_PAGE_FAULT | |
3219 | { | |
3220 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3221 | ret = FALSE; | |
3222 | } | |
3223 | __ENDTRY | |
3224 | return ret; | |
3225 | } | |
3226 | ||
e03864a2 JL |
3227 | static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded, |
3228 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
3229 | DWORD *pcbDecoded) | |
f224b34e JL |
3230 | { |
3231 | BOOL ret; | |
9153d39c | 3232 | DWORD bytesNeeded, dataLen; |
f224b34e | 3233 | |
9153d39c | 3234 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) |
f224b34e | 3235 | { |
9153d39c | 3236 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); |
f224b34e | 3237 | |
9153d39c | 3238 | bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); |
2e8ae598 JL |
3239 | if (pcbDecoded) |
3240 | *pcbDecoded = 1 + lenBytes + dataLen; | |
9153d39c JL |
3241 | if (!pvStructInfo) |
3242 | *pcbStructInfo = bytesNeeded; | |
3243 | else if (*pcbStructInfo < bytesNeeded) | |
f224b34e | 3244 | { |
9153d39c JL |
3245 | *pcbStructInfo = bytesNeeded; |
3246 | SetLastError(ERROR_MORE_DATA); | |
3247 | ret = FALSE; | |
3248 | } | |
3249 | else | |
3250 | { | |
3251 | CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; | |
f224b34e | 3252 | |
9153d39c JL |
3253 | blob->cbData = dataLen; |
3254 | assert(blob->pbData); | |
3255 | if (blob->cbData) | |
f224b34e | 3256 | { |
9153d39c | 3257 | DWORD i; |
f224b34e | 3258 | |
9153d39c | 3259 | for (i = 0; i < blob->cbData; i++) |
f224b34e | 3260 | { |
9153d39c JL |
3261 | blob->pbData[i] = *(pbEncoded + 1 + lenBytes + |
3262 | dataLen - i - 1); | |
f224b34e JL |
3263 | } |
3264 | } | |
3265 | } | |
3266 | } | |
f224b34e JL |
3267 | return ret; |
3268 | } | |
3269 | ||
3270 | static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType, | |
3271 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3272 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3273 | { | |
3274 | BOOL ret; | |
3275 | ||
3276 | __TRY | |
3277 | { | |
3278 | DWORD bytesNeeded; | |
3279 | ||
9153d39c JL |
3280 | if (pbEncoded[0] != ASN_INTEGER) |
3281 | { | |
3282 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3283 | ret = FALSE; | |
3284 | } | |
3285 | else | |
e03864a2 JL |
3286 | ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, |
3287 | dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); | |
9153d39c | 3288 | if (ret) |
f224b34e JL |
3289 | { |
3290 | if (!pvStructInfo) | |
3291 | *pcbStructInfo = bytesNeeded; | |
3292 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3293 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3294 | { | |
3295 | CRYPT_INTEGER_BLOB *blob; | |
3296 | ||
3297 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3298 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3299 | blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; | |
3300 | blob->pbData = (BYTE *)pvStructInfo + | |
3301 | sizeof(CRYPT_INTEGER_BLOB); | |
e03864a2 JL |
3302 | ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, |
3303 | dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo, | |
3304 | &bytesNeeded, NULL); | |
f224b34e JL |
3305 | } |
3306 | } | |
3307 | } | |
3308 | __EXCEPT_PAGE_FAULT | |
3309 | { | |
3310 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3311 | ret = FALSE; | |
3312 | } | |
3313 | __ENDTRY | |
3314 | return ret; | |
3315 | } | |
3316 | ||
e03864a2 JL |
3317 | static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded, |
3318 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
3319 | DWORD *pcbDecoded) | |
f224b34e JL |
3320 | { |
3321 | BOOL ret; | |
3322 | ||
3323 | if (pbEncoded[0] == ASN_INTEGER) | |
3324 | { | |
3325 | DWORD bytesNeeded, dataLen; | |
3326 | ||
3327 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
3328 | { | |
3329 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
3330 | ||
2e8ae598 JL |
3331 | if (pcbDecoded) |
3332 | *pcbDecoded = 1 + lenBytes + dataLen; | |
f224b34e JL |
3333 | bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB); |
3334 | if (!pvStructInfo) | |
3335 | *pcbStructInfo = bytesNeeded; | |
3336 | else if (*pcbStructInfo < bytesNeeded) | |
3337 | { | |
3338 | *pcbStructInfo = bytesNeeded; | |
3339 | SetLastError(ERROR_MORE_DATA); | |
3340 | ret = FALSE; | |
3341 | } | |
3342 | else | |
3343 | { | |
3344 | CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; | |
3345 | ||
3346 | blob->cbData = dataLen; | |
3347 | assert(blob->pbData); | |
3348 | /* remove leading zero byte if it exists */ | |
3349 | if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0) | |
3350 | { | |
3351 | blob->cbData--; | |
3352 | blob->pbData++; | |
3353 | } | |
3354 | if (blob->cbData) | |
3355 | { | |
3356 | DWORD i; | |
3357 | ||
3358 | for (i = 0; i < blob->cbData; i++) | |
3359 | { | |
3360 | blob->pbData[i] = *(pbEncoded + 1 + lenBytes + | |
3361 | dataLen - i - 1); | |
3362 | } | |
3363 | } | |
3364 | } | |
3365 | } | |
3366 | } | |
3367 | else | |
3368 | { | |
3369 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3370 | ret = FALSE; | |
3371 | } | |
3372 | return ret; | |
3373 | } | |
3374 | ||
3375 | static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType, | |
3376 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3377 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3378 | { | |
3379 | BOOL ret; | |
3380 | ||
3381 | __TRY | |
3382 | { | |
3383 | DWORD bytesNeeded; | |
3384 | ||
e03864a2 JL |
3385 | if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded, |
3386 | dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) | |
f224b34e JL |
3387 | { |
3388 | if (!pvStructInfo) | |
3389 | *pcbStructInfo = bytesNeeded; | |
3390 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3391 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3392 | { | |
3393 | CRYPT_INTEGER_BLOB *blob; | |
3394 | ||
3395 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3396 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3397 | blob = (CRYPT_INTEGER_BLOB *)pvStructInfo; | |
3398 | blob->pbData = (BYTE *)pvStructInfo + | |
3399 | sizeof(CRYPT_INTEGER_BLOB); | |
e03864a2 JL |
3400 | ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, |
3401 | cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo, | |
3402 | &bytesNeeded, NULL); | |
f224b34e JL |
3403 | } |
3404 | } | |
3405 | } | |
3406 | __EXCEPT_PAGE_FAULT | |
3407 | { | |
3408 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3409 | ret = FALSE; | |
3410 | } | |
3411 | __ENDTRY | |
3412 | return ret; | |
3413 | } | |
3414 | ||
3415 | static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType, | |
3416 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3417 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3418 | { | |
3419 | BOOL ret; | |
3420 | ||
3421 | if (!pvStructInfo) | |
3422 | { | |
3423 | *pcbStructInfo = sizeof(int); | |
3424 | return TRUE; | |
3425 | } | |
3426 | __TRY | |
3427 | { | |
3428 | if (pbEncoded[0] == ASN_ENUMERATED) | |
3429 | { | |
3430 | unsigned int val = 0, i; | |
3431 | ||
3432 | if (cbEncoded <= 1) | |
3433 | { | |
3434 | SetLastError(CRYPT_E_ASN1_EOD); | |
3435 | ret = FALSE; | |
3436 | } | |
3437 | else if (pbEncoded[1] == 0) | |
3438 | { | |
3439 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
3440 | ret = FALSE; | |
3441 | } | |
3442 | else | |
3443 | { | |
3444 | /* A little strange looking, but we have to accept a sign byte: | |
3445 | * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also, | |
3446 | * assuming a small length is okay here, it has to be in short | |
3447 | * form. | |
3448 | */ | |
3449 | if (pbEncoded[1] > sizeof(unsigned int) + 1) | |
3450 | { | |
3451 | SetLastError(CRYPT_E_ASN1_LARGE); | |
3452 | return FALSE; | |
3453 | } | |
3454 | for (i = 0; i < pbEncoded[1]; i++) | |
3455 | { | |
3456 | val <<= 8; | |
3457 | val |= pbEncoded[2 + i]; | |
3458 | } | |
3459 | if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3460 | pvStructInfo, pcbStructInfo, sizeof(unsigned int)))) | |
3461 | { | |
3462 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3463 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3464 | memcpy(pvStructInfo, &val, sizeof(unsigned int)); | |
3465 | } | |
3466 | } | |
3467 | } | |
3468 | else | |
3469 | { | |
3470 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3471 | ret = FALSE; | |
3472 | } | |
3473 | } | |
3474 | __EXCEPT_PAGE_FAULT | |
3475 | { | |
3476 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3477 | ret = FALSE; | |
3478 | } | |
3479 | __ENDTRY | |
3480 | return ret; | |
3481 | } | |
3482 | ||
3483 | /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE | |
3484 | * if it fails. | |
3485 | */ | |
3486 | #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \ | |
3487 | do { \ | |
3488 | BYTE i; \ | |
3489 | \ | |
3490 | (word) = 0; \ | |
3491 | for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \ | |
3492 | { \ | |
3493 | if (!isdigit(*(pbEncoded))) \ | |
3494 | { \ | |
3495 | SetLastError(CRYPT_E_ASN1_CORRUPT); \ | |
3496 | ret = FALSE; \ | |
3497 | } \ | |
3498 | else \ | |
3499 | { \ | |
3500 | (word) *= 10; \ | |
3501 | (word) += *(pbEncoded)++ - '0'; \ | |
3502 | } \ | |
3503 | } \ | |
3504 | } while (0) | |
3505 | ||
3506 | static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len, | |
3507 | SYSTEMTIME *sysTime) | |
3508 | { | |
21246938 | 3509 | BOOL ret = TRUE; |
f224b34e | 3510 | |
21246938 | 3511 | if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-')) |
f224b34e | 3512 | { |
21246938 JL |
3513 | WORD hours, minutes = 0; |
3514 | BYTE sign = *pbEncoded++; | |
f224b34e | 3515 | |
21246938 JL |
3516 | len--; |
3517 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours); | |
3518 | if (ret && hours >= 24) | |
3519 | { | |
3520 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
3521 | ret = FALSE; | |
3522 | } | |
3523 | else if (len >= 2) | |
3524 | { | |
3525 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes); | |
3526 | if (ret && minutes >= 60) | |
f224b34e JL |
3527 | { |
3528 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
3529 | ret = FALSE; | |
3530 | } | |
21246938 JL |
3531 | } |
3532 | if (ret) | |
3533 | { | |
3534 | if (sign == '+') | |
f224b34e | 3535 | { |
21246938 JL |
3536 | sysTime->wHour += hours; |
3537 | sysTime->wMinute += minutes; | |
f224b34e | 3538 | } |
21246938 | 3539 | else |
f224b34e | 3540 | { |
21246938 | 3541 | if (hours > sysTime->wHour) |
f224b34e | 3542 | { |
21246938 JL |
3543 | sysTime->wDay--; |
3544 | sysTime->wHour = 24 - (hours - sysTime->wHour); | |
f224b34e JL |
3545 | } |
3546 | else | |
21246938 JL |
3547 | sysTime->wHour -= hours; |
3548 | if (minutes > sysTime->wMinute) | |
f224b34e | 3549 | { |
21246938 JL |
3550 | sysTime->wHour--; |
3551 | sysTime->wMinute = 60 - (minutes - sysTime->wMinute); | |
f224b34e | 3552 | } |
21246938 JL |
3553 | else |
3554 | sysTime->wMinute -= minutes; | |
f224b34e JL |
3555 | } |
3556 | } | |
3557 | } | |
f224b34e JL |
3558 | return ret; |
3559 | } | |
3560 | ||
3561 | #define MIN_ENCODED_TIME_LENGTH 10 | |
3562 | ||
a538e95c JL |
3563 | static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded, |
3564 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
3565 | DWORD *pcbDecoded) | |
f224b34e | 3566 | { |
a538e95c | 3567 | BOOL ret = FALSE; |
f224b34e | 3568 | |
a538e95c | 3569 | if (pbEncoded[0] == ASN_UTCTIME) |
f224b34e | 3570 | { |
a538e95c JL |
3571 | if (cbEncoded <= 1) |
3572 | SetLastError(CRYPT_E_ASN1_EOD); | |
3573 | else if (pbEncoded[1] > 0x7f) | |
f224b34e | 3574 | { |
a538e95c JL |
3575 | /* long-form date strings really can't be valid */ |
3576 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
3577 | } | |
3578 | else | |
3579 | { | |
3580 | SYSTEMTIME sysTime = { 0 }; | |
3581 | BYTE len = pbEncoded[1]; | |
3582 | ||
3583 | if (len < MIN_ENCODED_TIME_LENGTH) | |
f224b34e | 3584 | SetLastError(CRYPT_E_ASN1_CORRUPT); |
f224b34e JL |
3585 | else |
3586 | { | |
a538e95c | 3587 | ret = TRUE; |
2e8ae598 JL |
3588 | if (pcbDecoded) |
3589 | *pcbDecoded = 2 + len; | |
a538e95c JL |
3590 | pbEncoded += 2; |
3591 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear); | |
3592 | if (sysTime.wYear >= 50) | |
3593 | sysTime.wYear += 1900; | |
3594 | else | |
3595 | sysTime.wYear += 2000; | |
3596 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth); | |
3597 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay); | |
3598 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour); | |
3599 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute); | |
3600 | if (ret && len > 0) | |
f224b34e | 3601 | { |
a538e95c JL |
3602 | if (len >= 2 && isdigit(*pbEncoded) && |
3603 | isdigit(*(pbEncoded + 1))) | |
3604 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, | |
3605 | sysTime.wSecond); | |
3606 | else if (isdigit(*pbEncoded)) | |
3607 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1, | |
3608 | sysTime.wSecond); | |
3609 | if (ret) | |
3610 | ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len, | |
3611 | &sysTime); | |
f224b34e | 3612 | } |
a538e95c | 3613 | if (ret) |
f224b34e | 3614 | { |
a538e95c JL |
3615 | if (!pvStructInfo) |
3616 | *pcbStructInfo = sizeof(FILETIME); | |
8c5bd5f5 JL |
3617 | else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, |
3618 | sizeof(FILETIME)))) | |
f224b34e JL |
3619 | ret = SystemTimeToFileTime(&sysTime, |
3620 | (FILETIME *)pvStructInfo); | |
f224b34e JL |
3621 | } |
3622 | } | |
3623 | } | |
a538e95c JL |
3624 | } |
3625 | else | |
3626 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3627 | return ret; | |
3628 | } | |
3629 | ||
3630 | static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType, | |
3631 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3632 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3633 | { | |
3634 | BOOL ret = FALSE; | |
3635 | ||
3636 | __TRY | |
3637 | { | |
3638 | DWORD bytesNeeded; | |
3639 | ||
3640 | ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded, | |
3641 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); | |
3642 | if (ret) | |
f224b34e | 3643 | { |
a538e95c JL |
3644 | if (!pvStructInfo) |
3645 | *pcbStructInfo = bytesNeeded; | |
3646 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, | |
3647 | pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3648 | { | |
3649 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3650 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3651 | ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded, | |
3652 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
3653 | &bytesNeeded, NULL); | |
3654 | } | |
f224b34e JL |
3655 | } |
3656 | } | |
3657 | __EXCEPT_PAGE_FAULT | |
3658 | { | |
3659 | SetLastError(STATUS_ACCESS_VIOLATION); | |
f224b34e JL |
3660 | } |
3661 | __ENDTRY | |
3662 | return ret; | |
3663 | } | |
3664 | ||
a538e95c JL |
3665 | static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded, |
3666 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
3667 | DWORD *pcbDecoded) | |
f224b34e | 3668 | { |
a538e95c | 3669 | BOOL ret = FALSE; |
f224b34e | 3670 | |
a538e95c | 3671 | if (pbEncoded[0] == ASN_GENERALTIME) |
f224b34e | 3672 | { |
a538e95c JL |
3673 | if (cbEncoded <= 1) |
3674 | SetLastError(CRYPT_E_ASN1_EOD); | |
3675 | else if (pbEncoded[1] > 0x7f) | |
f224b34e | 3676 | { |
a538e95c JL |
3677 | /* long-form date strings really can't be valid */ |
3678 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
3679 | } | |
3680 | else | |
3681 | { | |
3682 | BYTE len = pbEncoded[1]; | |
3683 | ||
3684 | if (len < MIN_ENCODED_TIME_LENGTH) | |
f224b34e | 3685 | SetLastError(CRYPT_E_ASN1_CORRUPT); |
f224b34e JL |
3686 | else |
3687 | { | |
a538e95c | 3688 | SYSTEMTIME sysTime = { 0 }; |
f224b34e | 3689 | |
a538e95c | 3690 | ret = TRUE; |
2e8ae598 JL |
3691 | if (pcbDecoded) |
3692 | *pcbDecoded = 2 + len; | |
a538e95c JL |
3693 | pbEncoded += 2; |
3694 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear); | |
3695 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth); | |
3696 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay); | |
3697 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour); | |
3698 | if (ret && len > 0) | |
f224b34e | 3699 | { |
a538e95c JL |
3700 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, |
3701 | sysTime.wMinute); | |
f224b34e | 3702 | if (ret && len > 0) |
f224b34e | 3703 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, |
a538e95c JL |
3704 | sysTime.wSecond); |
3705 | if (ret && len > 0 && (*pbEncoded == '.' || | |
3706 | *pbEncoded == ',')) | |
3707 | { | |
3708 | BYTE digits; | |
3709 | ||
3710 | pbEncoded++; | |
3711 | len--; | |
3712 | /* workaround macro weirdness */ | |
3713 | digits = min(len, 3); | |
3714 | CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits, | |
3715 | sysTime.wMilliseconds); | |
f224b34e | 3716 | } |
a538e95c JL |
3717 | if (ret) |
3718 | ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len, | |
3719 | &sysTime); | |
3720 | } | |
3721 | if (ret) | |
3722 | { | |
3723 | if (!pvStructInfo) | |
3724 | *pcbStructInfo = sizeof(FILETIME); | |
8c5bd5f5 JL |
3725 | else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, |
3726 | sizeof(FILETIME)))) | |
f224b34e JL |
3727 | ret = SystemTimeToFileTime(&sysTime, |
3728 | (FILETIME *)pvStructInfo); | |
f224b34e JL |
3729 | } |
3730 | } | |
3731 | } | |
f224b34e | 3732 | } |
a538e95c JL |
3733 | else |
3734 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3735 | return ret; | |
3736 | } | |
3737 | ||
3738 | static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded, | |
3739 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
3740 | DWORD *pcbDecoded) | |
3741 | { | |
3742 | BOOL ret; | |
3743 | InternalDecodeFunc decode = NULL; | |
3744 | ||
3745 | if (pbEncoded[0] == ASN_UTCTIME) | |
3746 | decode = CRYPT_AsnDecodeUtcTimeInternal; | |
3747 | else if (pbEncoded[0] == ASN_GENERALTIME) | |
3748 | decode = CRYPT_AsnDecodeGeneralizedTime; | |
3749 | if (decode) | |
3750 | ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo, | |
3751 | pcbStructInfo, pcbDecoded); | |
3752 | else | |
f224b34e | 3753 | { |
a538e95c | 3754 | SetLastError(CRYPT_E_ASN1_BADTAG); |
f224b34e JL |
3755 | ret = FALSE; |
3756 | } | |
f224b34e JL |
3757 | return ret; |
3758 | } | |
3759 | ||
3760 | static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType, | |
3761 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3762 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3763 | { | |
3764 | BOOL ret; | |
3765 | ||
3766 | __TRY | |
3767 | { | |
a538e95c JL |
3768 | DWORD bytesNeeded; |
3769 | ||
3770 | ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded, | |
3771 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL); | |
3772 | if (ret) | |
f224b34e | 3773 | { |
a538e95c JL |
3774 | if (!pvStructInfo) |
3775 | *pcbStructInfo = bytesNeeded; | |
3776 | else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3777 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3778 | { | |
3779 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3780 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3781 | ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded, | |
3782 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
3783 | &bytesNeeded, NULL); | |
3784 | } | |
f224b34e JL |
3785 | } |
3786 | } | |
3787 | __EXCEPT_PAGE_FAULT | |
3788 | { | |
3789 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3790 | ret = FALSE; | |
3791 | } | |
3792 | __ENDTRY | |
3793 | return ret; | |
3794 | } | |
3795 | ||
3796 | static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType, | |
3797 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3798 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3799 | { | |
3800 | BOOL ret = TRUE; | |
3801 | ||
3802 | __TRY | |
3803 | { | |
3804 | if (pbEncoded[0] == ASN_SEQUENCEOF) | |
3805 | { | |
3806 | DWORD bytesNeeded, dataLen, remainingLen, cValue; | |
3807 | ||
3808 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
3809 | { | |
3810 | BYTE lenBytes; | |
3811 | const BYTE *ptr; | |
3812 | ||
3813 | lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
3814 | bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY); | |
3815 | cValue = 0; | |
3816 | ptr = pbEncoded + 1 + lenBytes; | |
3817 | remainingLen = dataLen; | |
3818 | while (ret && remainingLen) | |
3819 | { | |
3820 | DWORD nextLen; | |
3821 | ||
3822 | ret = CRYPT_GetLen(ptr, remainingLen, &nextLen); | |
3823 | if (ret) | |
3824 | { | |
3825 | DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]); | |
3826 | ||
3827 | remainingLen -= 1 + nextLenBytes + nextLen; | |
3828 | ptr += 1 + nextLenBytes + nextLen; | |
3829 | bytesNeeded += sizeof(CRYPT_DER_BLOB); | |
3830 | if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) | |
3831 | bytesNeeded += 1 + nextLenBytes + nextLen; | |
3832 | cValue++; | |
3833 | } | |
3834 | } | |
3835 | if (ret) | |
3836 | { | |
3837 | CRYPT_SEQUENCE_OF_ANY *seq; | |
3838 | BYTE *nextPtr; | |
3839 | DWORD i; | |
3840 | ||
3841 | if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
3842 | pvStructInfo, pcbStructInfo, bytesNeeded))) | |
3843 | { | |
3844 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
3845 | pvStructInfo = *(BYTE **)pvStructInfo; | |
3846 | seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo; | |
3847 | seq->cValue = cValue; | |
3848 | seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq + | |
3849 | sizeof(*seq)); | |
3850 | nextPtr = (BYTE *)seq->rgValue + | |
3851 | cValue * sizeof(CRYPT_DER_BLOB); | |
3852 | ptr = pbEncoded + 1 + lenBytes; | |
3853 | remainingLen = dataLen; | |
3854 | i = 0; | |
3855 | while (ret && remainingLen) | |
3856 | { | |
3857 | DWORD nextLen; | |
3858 | ||
3859 | ret = CRYPT_GetLen(ptr, remainingLen, &nextLen); | |
3860 | if (ret) | |
3861 | { | |
3862 | DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]); | |
3863 | ||
3864 | seq->rgValue[i].cbData = 1 + nextLenBytes + | |
3865 | nextLen; | |
3866 | if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) | |
3867 | seq->rgValue[i].pbData = (BYTE *)ptr; | |
3868 | else | |
3869 | { | |
3870 | seq->rgValue[i].pbData = nextPtr; | |
3871 | memcpy(nextPtr, ptr, 1 + nextLenBytes + | |
3872 | nextLen); | |
3873 | nextPtr += 1 + nextLenBytes + nextLen; | |
3874 | } | |
3875 | remainingLen -= 1 + nextLenBytes + nextLen; | |
3876 | ptr += 1 + nextLenBytes + nextLen; | |
3877 | i++; | |
3878 | } | |
3879 | } | |
3880 | } | |
3881 | } | |
3882 | } | |
3883 | } | |
3884 | else | |
3885 | { | |
3886 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
1811acc2 | 3887 | ret = FALSE; |
f224b34e JL |
3888 | } |
3889 | } | |
3890 | __EXCEPT_PAGE_FAULT | |
3891 | { | |
3892 | SetLastError(STATUS_ACCESS_VIOLATION); | |
3893 | ret = FALSE; | |
3894 | } | |
3895 | __ENDTRY | |
3896 | return ret; | |
3897 | } | |
3898 | ||
e03864a2 JL |
3899 | static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded, |
3900 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
3901 | DWORD *pcbDecoded) | |
1811acc2 JL |
3902 | { |
3903 | BOOL ret; | |
3904 | ||
3905 | if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)) | |
3906 | { | |
3907 | DWORD bytesNeeded, dataLen; | |
3908 | ||
3909 | if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) | |
3910 | { | |
3911 | struct AsnArrayDescriptor arrayDesc = { | |
3912 | ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry, | |
3913 | sizeof(CERT_ALT_NAME_ENTRY), TRUE, | |
3914 | offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) }; | |
3915 | BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); | |
3916 | ||
3917 | if (dataLen) | |
3918 | { | |
3919 | DWORD nameLen; | |
3920 | ||
3921 | ret = CRYPT_AsnDecodeArray(&arrayDesc, | |
3922 | pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, | |
b2f02f3b | 3923 | 0, NULL, NULL, &nameLen, NULL, NULL); |
1811acc2 JL |
3924 | bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen; |
3925 | } | |
3926 | else | |
3927 | bytesNeeded = sizeof(CRL_DIST_POINT_NAME); | |
2e8ae598 JL |
3928 | if (pcbDecoded) |
3929 | *pcbDecoded = 1 + lenBytes + dataLen; | |
1811acc2 JL |
3930 | if (!pvStructInfo) |
3931 | *pcbStructInfo = bytesNeeded; | |
3932 | else if (*pcbStructInfo < bytesNeeded) | |
3933 | { | |
3934 | *pcbStructInfo = bytesNeeded; | |
3935 | SetLastError(ERROR_MORE_DATA); | |
3936 | ret = FALSE; | |
3937 | } | |
3938 | else | |
3939 | { | |
3940 | CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo; | |
3941 | ||
3942 | if (dataLen) | |
3943 | { | |
3944 | name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; | |
3945 | ret = CRYPT_AsnDecodeArray(&arrayDesc, | |
3946 | pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, | |
b2f02f3b | 3947 | 0, NULL, &name->u.FullName, pcbStructInfo, NULL, |
1811acc2 JL |
3948 | name->u.FullName.rgAltEntry); |
3949 | } | |
3950 | else | |
3951 | name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME; | |
3952 | } | |
3953 | } | |
3954 | } | |
3955 | else | |
3956 | { | |
3957 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
3958 | ret = FALSE; | |
3959 | } | |
3960 | return ret; | |
3961 | } | |
3962 | ||
731d37b0 JL |
3963 | static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded, |
3964 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
f224b34e JL |
3965 | { |
3966 | struct AsnDecodeSequenceItem items[] = { | |
3967 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT, | |
1811acc2 | 3968 | DistPointName), CRYPT_AsnDecodeDistPointName, |
f224b34e JL |
3969 | sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT, |
3970 | DistPointName.u.FullName.rgAltEntry), 0 }, | |
3971 | { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags), | |
3972 | CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, | |
3973 | offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 }, | |
3974 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer), | |
3975 | CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE, | |
3976 | offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 }, | |
3977 | }; | |
3978 | BOOL ret; | |
3979 | ||
ce47433d JL |
3980 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
3981 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, | |
3982 | pcbDecoded, NULL); | |
f224b34e JL |
3983 | return ret; |
3984 | } | |
3985 | ||
3986 | static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType, | |
3987 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
3988 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
3989 | { | |
3990 | BOOL ret; | |
3991 | ||
f3a1f2bf | 3992 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
3993 | pDecodePara, pvStructInfo, *pcbStructInfo); |
3994 | ||
3995 | __TRY | |
3996 | { | |
3997 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
3998 | CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE, | |
3999 | offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) }; | |
4000 | ||
4001 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
b2f02f3b | 4002 | pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); |
f224b34e JL |
4003 | } |
4004 | __EXCEPT_PAGE_FAULT | |
4005 | { | |
4006 | SetLastError(STATUS_ACCESS_VIOLATION); | |
4007 | ret = FALSE; | |
4008 | } | |
4009 | __ENDTRY | |
4010 | return ret; | |
4011 | } | |
4012 | ||
4013 | static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType, | |
4014 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
4015 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
4016 | { | |
4017 | BOOL ret; | |
4018 | ||
f3a1f2bf | 4019 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
f224b34e JL |
4020 | pDecodePara, pvStructInfo, *pcbStructInfo); |
4021 | ||
4022 | __TRY | |
4023 | { | |
4024 | struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, | |
4025 | CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 }; | |
4026 | ||
4027 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
b2f02f3b | 4028 | pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL); |
f224b34e JL |
4029 | } |
4030 | __EXCEPT_PAGE_FAULT | |
4031 | { | |
4032 | SetLastError(STATUS_ACCESS_VIOLATION); | |
4033 | ret = FALSE; | |
4034 | } | |
4035 | __ENDTRY | |
4036 | return ret; | |
4037 | } | |
4038 | ||
cb2e21ff JL |
4039 | static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType, |
4040 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
4041 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
4042 | { | |
4043 | BOOL ret; | |
4044 | ||
f3a1f2bf | 4045 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
cb2e21ff JL |
4046 | pDecodePara, pvStructInfo, *pcbStructInfo); |
4047 | ||
4048 | __TRY | |
4049 | { | |
4050 | struct AsnDecodeSequenceItem items[] = { | |
4051 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT, | |
4052 | DistPointName), CRYPT_AsnDecodeDistPointName, | |
4053 | sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, | |
4054 | offsetof(CRL_ISSUING_DIST_POINT, | |
4055 | DistPointName.u.FullName.rgAltEntry), 0 }, | |
4056 | { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT, | |
4057 | fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, | |
4058 | FALSE, 0 }, | |
4059 | { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT, | |
4060 | fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, | |
4061 | FALSE, 0 }, | |
4062 | { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT, | |
4063 | OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal, | |
4064 | sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT, | |
4065 | OnlySomeReasonFlags.pbData), 0 }, | |
4066 | { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT, | |
4067 | fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 }, | |
4068 | }; | |
4069 | ||
ce47433d JL |
4070 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
4071 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
4072 | pcbStructInfo, NULL, NULL); | |
cb2e21ff JL |
4073 | } |
4074 | __EXCEPT_PAGE_FAULT | |
4075 | { | |
4076 | SetLastError(STATUS_ACCESS_VIOLATION); | |
4077 | ret = FALSE; | |
4078 | } | |
4079 | __ENDTRY | |
4080 | return ret; | |
4081 | } | |
4082 | ||
c57a0848 JL |
4083 | static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded, |
4084 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
4085 | DWORD *pcbDecoded) | |
4086 | { | |
4087 | BOOL ret = FALSE; | |
4088 | ||
4089 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, | |
4090 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
4091 | ||
4092 | if (!cbEncoded) | |
4093 | { | |
4094 | SetLastError(CRYPT_E_ASN1_EOD); | |
4095 | return FALSE; | |
4096 | } | |
4097 | if (pbEncoded[0] != (ASN_CONTEXT | 1)) | |
4098 | { | |
4099 | SetLastError(CRYPT_E_ASN1_BADTAG); | |
4100 | return FALSE; | |
4101 | } | |
4102 | /* The BOOL is implicit: if the integer is present, then it's TRUE */ | |
4103 | ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, | |
4104 | pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo, | |
4105 | pcbDecoded); | |
4106 | if (ret && pvStructInfo) | |
4107 | *(BOOL *)pvStructInfo = TRUE; | |
4108 | TRACE("returning %d\n", ret); | |
4109 | return ret; | |
4110 | } | |
4111 | ||
4112 | static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded, | |
4113 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
4114 | DWORD *pcbDecoded) | |
4115 | { | |
4116 | BOOL ret; | |
4117 | struct AsnDecodeSequenceItem items[] = { | |
4118 | { 0, offsetof(CERT_GENERAL_SUBTREE, Base), | |
4119 | CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE, | |
4120 | offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 }, | |
4121 | { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum), | |
4122 | CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 }, | |
4123 | { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum), | |
4124 | CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0, | |
4125 | 0 }, | |
4126 | }; | |
4127 | CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo; | |
4128 | ||
4129 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, | |
4130 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
4131 | ||
4132 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), | |
4133 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, | |
4134 | pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL); | |
4135 | if (pcbDecoded) | |
4136 | { | |
4137 | TRACE("%d\n", *pcbDecoded); | |
4138 | if (*pcbDecoded < cbEncoded) | |
4139 | TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded), | |
4140 | *(pbEncoded + *pcbDecoded + 1)); | |
4141 | } | |
4142 | TRACE("returning %d\n", ret); | |
4143 | return ret; | |
4144 | } | |
4145 | ||
4146 | static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded, | |
4147 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
4148 | DWORD *pcbDecoded) | |
4149 | { | |
4150 | BOOL ret = TRUE; | |
4151 | struct AsnArrayDescriptor arrayDesc = { 0, | |
4152 | CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE, | |
4153 | offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) }; | |
4154 | struct GenericArray *array = (struct GenericArray *)pvStructInfo; | |
4155 | ||
4156 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, | |
4157 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
4158 | ||
4159 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
4160 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, | |
4161 | array ? array->rgItems : NULL); | |
4162 | return ret; | |
4163 | } | |
4164 | ||
4165 | ||
4166 | static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType, | |
4167 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
4168 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
4169 | { | |
4170 | BOOL ret = FALSE; | |
4171 | ||
4172 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, | |
4173 | pDecodePara, pvStructInfo, *pcbStructInfo); | |
4174 | ||
4175 | __TRY | |
4176 | { | |
4177 | struct AsnDecodeSequenceItem items[] = { | |
4178 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, | |
4179 | offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree), | |
4180 | CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE, | |
4181 | offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 }, | |
4182 | { ASN_CONTEXT | ASN_CONSTRUCTOR | 1, | |
4183 | offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree), | |
4184 | CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE, | |
4185 | offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 }, | |
4186 | }; | |
4187 | ||
4188 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), | |
4189 | pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, | |
4190 | pcbStructInfo, NULL, NULL); | |
4191 | } | |
4192 | __EXCEPT_PAGE_FAULT | |
4193 | { | |
4194 | SetLastError(STATUS_ACCESS_VIOLATION); | |
4195 | } | |
4196 | __ENDTRY | |
4197 | return ret; | |
4198 | } | |
4199 | ||
e03864a2 JL |
4200 | static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded, |
4201 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
4202 | DWORD *pcbDecoded) | |
d1ac9c73 JL |
4203 | { |
4204 | BOOL ret; | |
4205 | struct AsnDecodeSequenceItem items[] = { | |
4206 | { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob, | |
4207 | sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, | |
4208 | Issuer.pbData) }, | |
4209 | { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber), | |
4210 | CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, | |
4211 | TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 }, | |
4212 | }; | |
4213 | CERT_ISSUER_SERIAL_NUMBER *issuerSerial = | |
4214 | (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo; | |
4215 | ||
e03864a2 JL |
4216 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
4217 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
d1ac9c73 | 4218 | |
ce47433d | 4219 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
e03864a2 JL |
4220 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, |
4221 | pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL); | |
d1ac9c73 JL |
4222 | if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData) |
4223 | { | |
4224 | SetLastError(CRYPT_E_ASN1_CORRUPT); | |
4225 | ret = FALSE; | |
4226 | } | |
4227 | TRACE("returning %d\n", ret); | |
4228 | return ret; | |
4229 | } | |
4230 | ||
731d37b0 JL |
4231 | static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded, |
4232 | DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, | |
4233 | DWORD *pcbDecoded) | |
5900ab14 JL |
4234 | { |
4235 | CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo; | |
4236 | struct AsnDecodeSequenceItem items[] = { | |
4237 | { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion), | |
89a541a4 | 4238 | CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, |
5900ab14 JL |
4239 | { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer), |
4240 | CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER), | |
4241 | FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 }, | |
4242 | { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm), | |
4243 | CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), | |
4244 | FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 }, | |
4245 | { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, | |
4246 | offsetof(CMSG_SIGNER_INFO, AuthAttrs), | |
4247 | CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), | |
4248 | TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 }, | |
4249 | { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm), | |
4250 | CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), | |
4251 | FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, | |
4252 | HashEncryptionAlgorithm.pszObjId), 0 }, | |
4253 | { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash), | |
4254 | CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB), | |
4255 | FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 }, | |
4256 | { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, | |
4257 | offsetof(CMSG_SIGNER_INFO, UnauthAttrs), | |
4258 | CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), | |
4259 | TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 }, | |
4260 | }; | |
4261 | BOOL ret; | |
4262 | ||
731d37b0 JL |
4263 | TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, |
4264 | pvStructInfo, *pcbStructInfo); | |
5900ab14 | 4265 | |
ce47433d JL |
4266 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
4267 | pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo, | |
4268 | pcbDecoded, info ? info->Issuer.pbData : NULL); | |
5900ab14 JL |
4269 | return ret; |
4270 | } | |
4271 | ||
d1ac9c73 JL |
4272 | static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType, |
4273 | LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
4274 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
4275 | { | |
4276 | BOOL ret = FALSE; | |
4277 | ||
4278 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, | |
4279 | pDecodePara, pvStructInfo, *pcbStructInfo); | |
4280 | ||
4281 | __TRY | |
4282 | { | |
731d37b0 JL |
4283 | ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded, |
4284 | dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL); | |
5900ab14 JL |
4285 | if (ret && pvStructInfo) |
4286 | { | |
4287 | ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, | |
4288 | pcbStructInfo, *pcbStructInfo); | |
4289 | if (ret) | |
4290 | { | |
4291 | CMSG_SIGNER_INFO *info; | |
d1ac9c73 | 4292 | |
5900ab14 JL |
4293 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) |
4294 | pvStructInfo = *(BYTE **)pvStructInfo; | |
4295 | info = (CMSG_SIGNER_INFO *)pvStructInfo; | |
4296 | info->Issuer.pbData = ((BYTE *)info + | |
4297 | sizeof(CMSG_SIGNER_INFO)); | |
731d37b0 JL |
4298 | ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, |
4299 | cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, | |
4300 | pcbStructInfo, NULL); | |
5900ab14 JL |
4301 | } |
4302 | } | |
d1ac9c73 JL |
4303 | } |
4304 | __EXCEPT_PAGE_FAULT | |
4305 | { | |
4306 | SetLastError(STATUS_ACCESS_VIOLATION); | |
4307 | } | |
4308 | __ENDTRY | |
4309 | TRACE("returning %d\n", ret); | |
4310 | return ret; | |
4311 | } | |
4312 | ||
e03864a2 JL |
4313 | static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded, |
4314 | DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) | |
3a85fa6b JL |
4315 | { |
4316 | BOOL ret; | |
4317 | struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF, | |
5900ab14 | 4318 | CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE, |
3a85fa6b JL |
4319 | offsetof(CMSG_SIGNER_INFO, Issuer.pbData) }; |
4320 | struct GenericArray *array = (struct GenericArray *)pvStructInfo; | |
4321 | ||
e03864a2 JL |
4322 | TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags, |
4323 | pvStructInfo, *pcbStructInfo, pcbDecoded); | |
3a85fa6b JL |
4324 | |
4325 | ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, | |
e03864a2 | 4326 | NULL, pvStructInfo, pcbStructInfo, pcbDecoded, |
b2f02f3b | 4327 | array ? array->rgItems : NULL); |
3a85fa6b JL |
4328 | return ret; |
4329 | } | |
4330 | ||
4331 | BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded, | |
4332 | DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, | |
4333 | CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo) | |
4334 | { | |
4335 | BOOL ret = FALSE; | |
4336 | struct AsnDecodeSequenceItem items[] = { | |
89a541a4 JL |
4337 | { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), |
4338 | CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 }, | |
3a85fa6b JL |
4339 | /* Placeholder for the hash algorithms - redundant with those in the |
4340 | * signers, so just ignore them. | |
4341 | */ | |
4342 | { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 }, | |
4343 | { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content), | |
4344 | CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO), | |
4345 | FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 }, | |
4346 | { ASN_CONSTRUCTOR | ASN_CONTEXT | 0, | |
4347 | offsetof(CRYPT_SIGNED_INFO, cCertEncoded), | |
4348 | CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE, | |
4349 | offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 }, | |
4350 | { ASN_CONSTRUCTOR | ASN_CONTEXT | 1, | |
4351 | offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray, | |
4352 | sizeof(struct GenericArray), TRUE, TRUE, | |
4353 | offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 }, | |
4354 | { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo), | |
4355 | CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE, | |
4356 | offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 }, | |
4357 | }; | |
4358 | ||
4359 | TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags, | |
4360 | pDecodePara, signedInfo, *pcbSignedInfo); | |
4361 | ||
ce47433d JL |
4362 | ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]), |
4363 | pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo, | |
4364 | NULL, NULL); | |
3a85fa6b JL |
4365 | TRACE("returning %d\n", ret); |
4366 | return ret; | |
4367 | } | |
4368 | ||
4c58c4bc JL |
4369 | static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType, |
4370 | LPCSTR lpszStructType) | |
f224b34e | 4371 | { |
f224b34e | 4372 | CryptDecodeObjectExFunc decodeFunc = NULL; |
f224b34e | 4373 | |
f224b34e JL |
4374 | if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING |
4375 | && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING) | |
4376 | { | |
4377 | SetLastError(ERROR_FILE_NOT_FOUND); | |
4c58c4bc | 4378 | return NULL; |
f224b34e | 4379 | } |
f224b34e JL |
4380 | if (!HIWORD(lpszStructType)) |
4381 | { | |
4382 | switch (LOWORD(lpszStructType)) | |
4383 | { | |
66787e65 | 4384 | case LOWORD(X509_CERT): |
1811acc2 | 4385 | decodeFunc = CRYPT_AsnDecodeCertSignedContent; |
f224b34e | 4386 | break; |
66787e65 | 4387 | case LOWORD(X509_CERT_TO_BE_SIGNED): |
1811acc2 | 4388 | decodeFunc = CRYPT_AsnDecodeCert; |
f224b34e | 4389 | break; |
66787e65 | 4390 | case LOWORD(X509_CERT_CRL_TO_BE_SIGNED): |
1811acc2 | 4391 | decodeFunc = CRYPT_AsnDecodeCRL; |
f224b34e | 4392 | break; |
66787e65 | 4393 | case LOWORD(X509_EXTENSIONS): |
f224b34e JL |
4394 | decodeFunc = CRYPT_AsnDecodeExtensions; |
4395 | break; | |
66787e65 | 4396 | case LOWORD(X509_NAME_VALUE): |
dd4bd4ad JL |
4397 | decodeFunc = CRYPT_AsnDecodeNameValue; |
4398 | break; | |
66787e65 | 4399 | case LOWORD(X509_NAME): |
f224b34e JL |
4400 | decodeFunc = CRYPT_AsnDecodeName; |
4401 | break; | |
66787e65 | 4402 | case LOWORD(X509_PUBLIC_KEY_INFO): |
f224b34e JL |
4403 | decodeFunc = CRYPT_AsnDecodePubKeyInfo; |
4404 | break; | |
66787e65 | 4405 | case LOWORD(X509_AUTHORITY_KEY_ID): |
9153d39c JL |
4406 | decodeFunc = CRYPT_AsnDecodeAuthorityKeyId; |
4407 | break; | |
66787e65 | 4408 | case LOWORD(X509_ALTERNATE_NAME): |
f224b34e JL |
4409 | decodeFunc = CRYPT_AsnDecodeAltName; |
4410 | break; | |
66787e65 | 4411 | case LOWORD(X509_BASIC_CONSTRAINTS): |
f224b34e JL |
4412 | decodeFunc = CRYPT_AsnDecodeBasicConstraints; |
4413 | break; | |
66787e65 | 4414 | case LOWORD(X509_BASIC_CONSTRAINTS2): |
f224b34e JL |
4415 | decodeFunc = CRYPT_AsnDecodeBasicConstraints2; |
4416 | break; | |
66787e65 | 4417 | case LOWORD(RSA_CSP_PUBLICKEYBLOB): |
f224b34e JL |
4418 | decodeFunc = CRYPT_AsnDecodeRsaPubKey; |
4419 | break; | |
66787e65 | 4420 | case LOWORD(X509_UNICODE_NAME): |
8ccbdb80 JL |
4421 | decodeFunc = CRYPT_AsnDecodeUnicodeName; |
4422 | break; | |
66787e65 | 4423 | case LOWORD(PKCS_ATTRIBUTE): |
97f2c658 JL |
4424 | decodeFunc = CRYPT_AsnDecodePKCSAttribute; |
4425 | break; | |
66787e65 | 4426 | case LOWORD(X509_UNICODE_NAME_VALUE): |
ead21189 JL |
4427 | decodeFunc = CRYPT_AsnDecodeUnicodeNameValue; |
4428 | break; | |
66787e65 | 4429 | case LOWORD(X509_OCTET_STRING): |
f224b34e JL |
4430 | decodeFunc = CRYPT_AsnDecodeOctets; |
4431 | break; | |
66787e65 AJ |
4432 | case LOWORD(X509_BITS): |
4433 | case LOWORD(X509_KEY_USAGE): | |
f224b34e JL |
4434 | decodeFunc = CRYPT_AsnDecodeBits; |
4435 | break; | |
66787e65 | 4436 | case LOWORD(X509_INTEGER): |
f224b34e JL |
4437 | decodeFunc = CRYPT_AsnDecodeInt; |
4438 | break; | |
66787e65 | 4439 | case LOWORD(X509_MULTI_BYTE_INTEGER): |
f224b34e JL |
4440 | decodeFunc = CRYPT_AsnDecodeInteger; |
4441 | break; | |
66787e65 | 4442 | case LOWORD(X509_MULTI_BYTE_UINT): |
f224b34e JL |
4443 | decodeFunc = CRYPT_AsnDecodeUnsignedInteger; |
4444 | break; | |
66787e65 | 4445 | case LOWORD(X509_ENUMERATED): |
f224b34e JL |
4446 | decodeFunc = CRYPT_AsnDecodeEnumerated; |
4447 | break; | |
66787e65 | 4448 | case LOWORD(X509_CHOICE_OF_TIME): |
f224b34e JL |
4449 | decodeFunc = CRYPT_AsnDecodeChoiceOfTime; |
4450 | break; | |
66787e65 | 4451 | case LOWORD(X509_AUTHORITY_KEY_ID2): |
2d00a4f0 JL |
4452 | decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2; |
4453 | break; | |
66787e65 | 4454 | case LOWORD(PKCS_CONTENT_INFO): |
1cd9510b JL |
4455 | decodeFunc = CRYPT_AsnDecodePKCSContentInfo; |
4456 | break; | |
66787e65 | 4457 | case LOWORD(X509_SEQUENCE_OF_ANY): |
f224b34e JL |
4458 | decodeFunc = CRYPT_AsnDecodeSequenceOfAny; |
4459 | break; | |
66787e65 | 4460 | case LOWORD(PKCS_UTC_TIME): |
f224b34e JL |
4461 | decodeFunc = CRYPT_AsnDecodeUtcTime; |
4462 | break; | |
66787e65 | 4463 | case LOWORD(X509_CRL_DIST_POINTS): |
f224b34e JL |
4464 | decodeFunc = CRYPT_AsnDecodeCRLDistPoints; |
4465 | break; | |
66787e65 | 4466 | case LOWORD(X509_ENHANCED_KEY_USAGE): |
f224b34e JL |
4467 | decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage; |
4468 | break; | |
66787e65 | 4469 | case LOWORD(PKCS_ATTRIBUTES): |
e1f83a7a JL |
4470 | decodeFunc = CRYPT_AsnDecodePKCSAttributes; |
4471 | break; | |
66787e65 | 4472 | case LOWORD(X509_ISSUING_DIST_POINT): |
cb2e21ff JL |
4473 | decodeFunc = CRYPT_AsnDecodeIssuingDistPoint; |
4474 | break; | |
66787e65 | 4475 | case LOWORD(X509_NAME_CONSTRAINTS): |
c57a0848 JL |
4476 | decodeFunc = CRYPT_AsnDecodeNameConstraints; |
4477 | break; | |
66787e65 | 4478 | case LOWORD(PKCS7_SIGNER_INFO): |
d1ac9c73 JL |
4479 | decodeFunc = CRYPT_AsnDecodePKCSSignerInfo; |
4480 | break; | |
f224b34e JL |
4481 | } |
4482 | } | |
4483 | else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS)) | |
4484 | decodeFunc = CRYPT_AsnDecodeExtensions; | |
4485 | else if (!strcmp(lpszStructType, szOID_RSA_signingTime)) | |
4486 | decodeFunc = CRYPT_AsnDecodeUtcTime; | |
9153d39c JL |
4487 | else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER)) |
4488 | decodeFunc = CRYPT_AsnDecodeAuthorityKeyId; | |
2d00a4f0 JL |
4489 | else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2)) |
4490 | decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2; | |
f224b34e JL |
4491 | else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE)) |
4492 | decodeFunc = CRYPT_AsnDecodeEnumerated; | |
4493 | else if (!strcmp(lpszStructType, szOID_KEY_USAGE)) | |
4494 | decodeFunc = CRYPT_AsnDecodeBits; | |
4495 | else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER)) | |
4496 | decodeFunc = CRYPT_AsnDecodeOctets; | |
4497 | else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS)) | |
4498 | decodeFunc = CRYPT_AsnDecodeBasicConstraints; | |
4499 | else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2)) | |
4500 | decodeFunc = CRYPT_AsnDecodeBasicConstraints2; | |
4501 | else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME)) | |
4502 | decodeFunc = CRYPT_AsnDecodeAltName; | |
4503 | else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2)) | |
4504 | decodeFunc = CRYPT_AsnDecodeAltName; | |
4505 | else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION)) | |
4506 | decodeFunc = CRYPT_AsnDecodeAltName; | |
4507 | else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME)) | |
4508 | decodeFunc = CRYPT_AsnDecodeAltName; | |
4509 | else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2)) | |
4510 | decodeFunc = CRYPT_AsnDecodeAltName; | |
4511 | else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS)) | |
4512 | decodeFunc = CRYPT_AsnDecodeCRLDistPoints; | |
4513 | else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE)) | |
4514 | decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage; | |
cb2e21ff JL |
4515 | else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT)) |
4516 | decodeFunc = CRYPT_AsnDecodeIssuingDistPoint; | |
c57a0848 JL |
4517 | else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS)) |
4518 | decodeFunc = CRYPT_AsnDecodeNameConstraints; | |
4c58c4bc JL |
4519 | return decodeFunc; |
4520 | } | |
4521 | ||
4522 | static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType, | |
4523 | LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) | |
4524 | { | |
4525 | static HCRYPTOIDFUNCSET set = NULL; | |
4526 | CryptDecodeObjectFunc decodeFunc = NULL; | |
4527 | ||
4528 | if (!set) | |
4529 | set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0); | |
4530 | CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, | |
4531 | (void **)&decodeFunc, hFunc); | |
4532 | return decodeFunc; | |
4533 | } | |
4534 | ||
4535 | static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType, | |
4536 | LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc) | |
4537 | { | |
4538 | static HCRYPTOIDFUNCSET set = NULL; | |
4539 | CryptDecodeObjectExFunc decodeFunc = NULL; | |
4540 | ||
4541 | if (!set) | |
4542 | set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0); | |
4543 | CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0, | |
4544 | (void **)&decodeFunc, hFunc); | |
4545 | return decodeFunc; | |
4546 | } | |
4547 | ||
4548 | BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType, | |
4549 | const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, | |
4550 | DWORD *pcbStructInfo) | |
4551 | { | |
4552 | BOOL ret = FALSE; | |
4553 | CryptDecodeObjectFunc pCryptDecodeObject = NULL; | |
4554 | CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL; | |
4555 | HCRYPTOIDFUNCADDR hFunc = NULL; | |
4556 | ||
4557 | TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType, | |
4558 | debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags, | |
4559 | pvStructInfo, pcbStructInfo); | |
4560 | ||
4561 | if (!pvStructInfo && !pcbStructInfo) | |
4562 | { | |
4563 | SetLastError(ERROR_INVALID_PARAMETER); | |
4564 | return FALSE; | |
4565 | } | |
5d8d9e7d JL |
4566 | if (!cbEncoded) |
4567 | { | |
4568 | SetLastError(CRYPT_E_ASN1_EOD); | |
4569 | return FALSE; | |
4570 | } | |
4571 | if (cbEncoded > MAX_ENCODED_LEN) | |
4572 | { | |
4573 | SetLastError(CRYPT_E_ASN1_LARGE); | |
4574 | return FALSE; | |
4575 | } | |
4c58c4bc JL |
4576 | |
4577 | if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType, | |
4578 | lpszStructType))) | |
4579 | { | |
3a50b1fe JL |
4580 | TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", |
4581 | debugstr_a(lpszStructType)); | |
4c58c4bc JL |
4582 | pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType, |
4583 | lpszStructType, &hFunc); | |
4584 | if (!pCryptDecodeObject) | |
4585 | pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType, | |
4586 | lpszStructType, &hFunc); | |
4587 | } | |
4588 | if (pCryptDecodeObject) | |
4589 | ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, | |
4590 | pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo); | |
4591 | else if (pCryptDecodeObjectEx) | |
4592 | ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType, | |
4593 | pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, | |
4594 | pvStructInfo, pcbStructInfo); | |
4595 | if (hFunc) | |
4596 | CryptFreeOIDFunctionAddress(hFunc, 0); | |
4597 | TRACE_(crypt)("returning %d\n", ret); | |
4598 | return ret; | |
4599 | } | |
4600 | ||
4601 | BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, | |
4602 | const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, | |
4603 | PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) | |
4604 | { | |
4605 | BOOL ret = FALSE; | |
4606 | CryptDecodeObjectExFunc decodeFunc; | |
4607 | HCRYPTOIDFUNCADDR hFunc = NULL; | |
4608 | ||
4609 | TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n", | |
4610 | dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded, | |
4611 | cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); | |
4612 | ||
4613 | if (!pvStructInfo && !pcbStructInfo) | |
f224b34e | 4614 | { |
4c58c4bc JL |
4615 | SetLastError(ERROR_INVALID_PARAMETER); |
4616 | return FALSE; | |
f224b34e | 4617 | } |
4c58c4bc JL |
4618 | if (!cbEncoded) |
4619 | { | |
4620 | SetLastError(CRYPT_E_ASN1_EOD); | |
4621 | return FALSE; | |
4622 | } | |
4623 | if (cbEncoded > MAX_ENCODED_LEN) | |
4624 | { | |
4625 | SetLastError(CRYPT_E_ASN1_LARGE); | |
4626 | return FALSE; | |
4627 | } | |
4628 | ||
4629 | SetLastError(NOERROR); | |
4630 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo) | |
4631 | *(BYTE **)pvStructInfo = NULL; | |
4632 | decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType); | |
4633 | if (!decodeFunc) | |
3a50b1fe JL |
4634 | { |
4635 | TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n", | |
4636 | debugstr_a(lpszStructType)); | |
4c58c4bc JL |
4637 | decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType, |
4638 | &hFunc); | |
3a50b1fe | 4639 | } |
f224b34e JL |
4640 | if (decodeFunc) |
4641 | ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded, | |
4642 | cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo); | |
4643 | else | |
038b53c3 | 4644 | { |
4c58c4bc JL |
4645 | CryptDecodeObjectFunc pCryptDecodeObject = |
4646 | CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc); | |
038b53c3 JL |
4647 | |
4648 | /* Try CryptDecodeObject function. Don't call CryptDecodeObject | |
4649 | * directly, as that could cause an infinite loop. | |
4650 | */ | |
038b53c3 JL |
4651 | if (pCryptDecodeObject) |
4652 | { | |
4653 | if (dwFlags & CRYPT_DECODE_ALLOC_FLAG) | |
4654 | { | |
4655 | ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, | |
4656 | pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo); | |
4657 | if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, | |
4658 | pvStructInfo, pcbStructInfo, *pcbStructInfo))) | |
4c58c4bc JL |
4659 | ret = pCryptDecodeObject(dwCertEncodingType, |
4660 | lpszStructType, pbEncoded, cbEncoded, dwFlags, | |
4661 | *(BYTE **)pvStructInfo, pcbStructInfo); | |
038b53c3 JL |
4662 | } |
4663 | else | |
4664 | ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType, | |
4665 | pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo); | |
4666 | } | |
038b53c3 | 4667 | } |
f224b34e JL |
4668 | if (hFunc) |
4669 | CryptFreeOIDFunctionAddress(hFunc, 0); | |
4c58c4bc | 4670 | TRACE_(crypt)("returning %d\n", ret); |
f224b34e JL |
4671 | return ret; |
4672 | } |