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