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