crypt32: Remove no-ops.
[wine/wine-gecko.git] / dlls / crypt32 / encode.c
blobe14ff19f98314bfa3372b1cf8b2d007a2c4721cd
1 /*
2 * Copyright 2005-2008 Juan Lang
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.
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.
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
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.
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.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
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"
52 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
53 WINE_DECLARE_DEBUG_CHANNEL(crypt);
55 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
56 BYTE *, DWORD *);
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.
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);
103 BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara,
104 BYTE *pbEncoded, DWORD *pcbEncoded, DWORD bytesNeeded)
106 BOOL ret = TRUE;
108 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
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;
119 else if (bytesNeeded > *pcbEncoded)
121 *pcbEncoded = bytesNeeded;
122 SetLastError(ERROR_MORE_DATA);
123 ret = FALSE;
125 else
126 *pcbEncoded = bytesNeeded;
127 return ret;
130 static void CRYPT_FreeSpace(const CRYPT_ENCODE_PARA *pEncodePara, LPVOID pv)
132 if (pEncodePara && pEncodePara->pfnFree)
133 pEncodePara->pfnFree(pv);
134 else
135 LocalFree(pv);
138 BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
140 DWORD bytesNeeded, significantBytes = 0;
142 if (len <= 0x7f)
143 bytesNeeded = 1;
144 else
146 DWORD temp;
148 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
149 temp <<= 8, significantBytes--)
151 bytesNeeded = significantBytes + 1;
153 if (!pbEncoded)
155 *pcbEncoded = bytesNeeded;
156 return TRUE;
158 if (*pcbEncoded < bytesNeeded)
160 SetLastError(ERROR_MORE_DATA);
161 return FALSE;
163 if (len <= 0x7f)
164 *pbEncoded = (BYTE)len;
165 else
167 DWORD i;
169 *pbEncoded++ = significantBytes | 0x80;
170 for (i = 0; i < significantBytes; i++)
172 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
173 len >>= 8;
176 *pcbEncoded = bytesNeeded;
177 return TRUE;
180 BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
181 struct AsnEncodeSequenceItem items[], DWORD cItem, DWORD dwFlags,
182 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
184 BOOL ret;
185 DWORD i, dataLen = 0;
187 TRACE("%p, %d, %08x, %p, %p, %d\n", items, cItem, dwFlags, pEncodePara,
188 pbEncoded, *pcbEncoded);
189 for (i = 0, ret = TRUE; ret && i < cItem; i++)
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;
199 if (ret)
201 DWORD lenBytes, bytesNeeded;
203 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
204 bytesNeeded = 1 + lenBytes + dataLen;
205 if (!pbEncoded)
206 *pcbEncoded = bytesNeeded;
207 else
209 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
210 pcbEncoded, bytesNeeded)))
212 BYTE *out;
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++)
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;
230 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
231 CRYPT_FreeSpace(pEncodePara, pbEncoded);
235 TRACE("returning %d (%08x)\n", ret, GetLastError());
236 return ret;
239 BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
240 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
241 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
243 BOOL ret;
244 const struct AsnConstructedItem *item = pvStructInfo;
245 DWORD len;
247 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
248 item->pvStructInfo, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &len)))
250 DWORD dataLen, bytesNeeded;
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)))
259 BYTE *out;
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)
272 /* Some functions propagate their errors through the size */
273 *pcbEncoded = len;
274 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
275 CRYPT_FreeSpace(pEncodePara, pbEncoded);
279 else
281 /* Some functions propagate their errors through the size */
282 *pcbEncoded = len;
284 return ret;
287 struct AsnEncodeTagSwappedItem
289 BYTE tag;
290 const void *pvStructInfo;
291 CryptEncodeObjectExFunc encodeFunc;
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.
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)
302 BOOL ret;
303 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
305 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
306 item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
307 if (ret && pbEncoded)
308 *pbEncoded = item->tag;
309 return ret;
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)
316 const DWORD *ver = pvStructInfo;
317 BOOL ret;
319 /* CERT_V1 is not encoded */
320 if (*ver == CERT_V1)
322 *pcbEncoded = 0;
323 ret = TRUE;
325 else
327 struct AsnConstructedItem item = { 0, ver, CRYPT_AsnEncodeInt };
329 ret = CRYPT_AsnEncodeConstructed(dwCertEncodingType, X509_INTEGER,
330 &item, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
332 return ret;
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)
339 const CRYPT_DER_BLOB *blob = pvStructInfo;
340 BOOL ret;
342 if (!pbEncoded)
344 *pcbEncoded = blob->cbData;
345 ret = TRUE;
347 else
349 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
350 pcbEncoded, blob->cbData)))
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;
359 return ret;
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)
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 },
374 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
375 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
376 pcbEncoded);
377 return ret;
380 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
381 * if they are empty.
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)
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 },
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 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
404 pcbEncoded);
405 return ret;
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)
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 },
419 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
420 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
421 pcbEncoded);
422 return ret;
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)
429 BOOL ret;
431 __TRY
433 const CERT_PUBLIC_KEY_INFO *info = pvStructInfo;
434 struct AsnEncodeSequenceItem items[] = {
435 { &info->Algorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
436 { &info->PublicKey, CRYPT_AsnEncodeBits, 0 },
439 TRACE("Encoding public key with OID %s\n",
440 debugstr_a(info->Algorithm.pszObjId));
441 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
442 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
443 pcbEncoded);
445 __EXCEPT_PAGE_FAULT
447 SetLastError(STATUS_ACCESS_VIOLATION);
448 ret = FALSE;
450 __ENDTRY
451 return ret;
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)
458 BOOL ret;
460 __TRY
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 },
469 if (dwFlags & CRYPT_ENCODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
470 items[2].encodeFunc = CRYPT_AsnEncodeBits;
471 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
472 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
473 pcbEncoded);
475 __EXCEPT_PAGE_FAULT
477 SetLastError(STATUS_ACCESS_VIOLATION);
478 ret = FALSE;
480 __ENDTRY
481 return ret;
484 BOOL WINAPI CRYPT_AsnEncodePubKeyInfoNoNull(DWORD dwCertEncodingType,
485 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
486 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
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 },
495 TRACE("Encoding public key with OID %s\n",
496 debugstr_a(info->Algorithm.pszObjId));
497 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
498 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
499 pcbEncoded);
500 return ret;
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.
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)
511 BOOL ret;
513 __TRY
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 }
526 struct AsnConstructedItem constructed = { 0 };
527 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
528 DWORD cItem = 7, cSwapped = 0;
530 if (info->IssuerUniqueId.cbData)
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++;
540 if (info->SubjectUniqueId.cbData)
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++;
550 if (info->cExtension)
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++;
560 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
561 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
563 __EXCEPT_PAGE_FAULT
565 SetLastError(STATUS_ACCESS_VIOLATION);
566 ret = FALSE;
568 __ENDTRY
569 return ret;
572 static BOOL CRYPT_AsnEncodeCRLEntry(const CRL_ENTRY *entry,
573 BYTE *pbEncoded, DWORD *pcbEncoded)
575 struct AsnEncodeSequenceItem items[3] = {
576 { &entry->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
577 { &entry->RevocationDate, CRYPT_AsnEncodeChoiceOfTime, 0 },
578 { 0 }
580 DWORD cItem = 2;
581 BOOL ret;
583 TRACE("%p, %p, %p\n", entry, pbEncoded, pcbEncoded);
585 if (entry->cExtension)
587 items[cItem].pvStructInfo = &entry->cExtension;
588 items[cItem].encodeFunc = CRYPT_AsnEncodeExtensions;
589 cItem++;
592 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
593 pbEncoded, pcbEncoded);
595 TRACE("returning %d (%08x)\n", ret, GetLastError());
596 return ret;
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)
603 DWORD bytesNeeded, dataLen, lenBytes, i;
604 const CRL_INFO *info = pvStructInfo;
605 const CRL_ENTRY *rgCRLEntry = info->rgCRLEntry;
606 BOOL ret = TRUE;
608 for (i = 0, dataLen = 0; ret && i < info->cCRLEntry; i++)
610 DWORD size;
612 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], NULL, &size);
613 if (ret)
614 dataLen += size;
616 if (ret)
618 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
619 bytesNeeded = 1 + lenBytes + dataLen;
620 if (!pbEncoded)
621 *pcbEncoded = bytesNeeded;
622 else
624 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
625 pcbEncoded, bytesNeeded)))
627 BYTE *out;
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++)
637 DWORD size = dataLen;
639 ret = CRYPT_AsnEncodeCRLEntry(&rgCRLEntry[i], out, &size);
640 out += size;
641 dataLen -= size;
643 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
644 CRYPT_FreeSpace(pEncodePara, pbEncoded);
648 return ret;
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)
655 const DWORD *ver = pvStructInfo;
656 BOOL ret;
658 /* CRL_V1 is not encoded */
659 if (*ver == CRL_V1)
661 *pcbEncoded = 0;
662 ret = TRUE;
664 else
665 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
666 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
667 return ret;
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.
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)
678 BOOL ret;
680 __TRY
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 }
690 struct AsnConstructedItem constructed[1] = { { 0 } };
691 DWORD cItem = 4, cConstructed = 0;
693 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
695 items[cItem].pvStructInfo = &info->NextUpdate;
696 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
697 cItem++;
699 if (info->cCRLEntry)
701 items[cItem].pvStructInfo = info;
702 items[cItem].encodeFunc = CRYPT_AsnEncodeCRLEntries;
703 cItem++;
705 if (info->cExtension)
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++;
716 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
717 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
719 __EXCEPT_PAGE_FAULT
721 SetLastError(STATUS_ACCESS_VIOLATION);
722 ret = FALSE;
724 __ENDTRY
725 return ret;
728 static BOOL CRYPT_AsnEncodeExtension(CERT_EXTENSION *ext, BYTE *pbEncoded,
729 DWORD *pcbEncoded)
731 BOOL ret;
732 struct AsnEncodeSequenceItem items[3] = {
733 { ext->pszObjId, CRYPT_AsnEncodeOid, 0 },
734 { NULL, NULL, 0 },
735 { NULL, NULL, 0 },
737 DWORD cItem = 1;
739 TRACE("%p, %p, %d\n", ext, pbEncoded, *pcbEncoded);
741 if (ext->fCritical)
743 items[cItem].pvStructInfo = &ext->fCritical;
744 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
745 cItem++;
747 items[cItem].pvStructInfo = &ext->Value;
748 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
749 cItem++;
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;
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)
761 BOOL ret;
763 __TRY
765 DWORD bytesNeeded, dataLen, lenBytes, i;
766 const CERT_EXTENSIONS *exts = pvStructInfo;
768 ret = TRUE;
769 for (i = 0, dataLen = 0; ret && i < exts->cExtension; i++)
771 DWORD size;
773 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i], NULL, &size);
774 if (ret)
775 dataLen += size;
777 if (ret)
779 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
780 bytesNeeded = 1 + lenBytes + dataLen;
781 if (!pbEncoded)
782 *pcbEncoded = bytesNeeded;
783 else
785 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
786 pbEncoded, pcbEncoded, bytesNeeded)))
788 BYTE *out;
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++)
798 DWORD size = dataLen;
800 ret = CRYPT_AsnEncodeExtension(&exts->rgExtension[i],
801 out, &size);
802 out += size;
803 dataLen -= size;
805 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
806 CRYPT_FreeSpace(pEncodePara, pbEncoded);
811 __EXCEPT_PAGE_FAULT
813 SetLastError(STATUS_ACCESS_VIOLATION);
814 ret = FALSE;
816 __ENDTRY
817 return ret;
820 BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
821 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
822 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
824 LPCSTR pszObjId = pvStructInfo;
825 DWORD bytesNeeded = 0, lenBytes;
826 BOOL ret = TRUE;
827 int firstPos = 0;
828 BYTE firstByte = 0;
830 TRACE("%s\n", debugstr_a(pszObjId));
832 if (pszObjId)
834 const char *ptr;
835 int val1, val2;
837 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
839 SetLastError(CRYPT_E_ASN1_ERROR);
840 return FALSE;
842 bytesNeeded++;
843 firstByte = val1 * 40 + val2;
844 ptr = pszObjId + firstPos;
845 if (*ptr == '.')
847 ptr++;
848 firstPos++;
850 while (ret && *ptr)
852 int pos;
854 /* note I assume each component is at most 32-bits long in base 2 */
855 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
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++;
871 else
873 SetLastError(CRYPT_E_ASN1_ERROR);
874 return FALSE;
877 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
879 else
880 lenBytes = 1;
881 bytesNeeded += 1 + lenBytes;
882 if (pbEncoded)
884 if (*pcbEncoded < bytesNeeded)
886 SetLastError(ERROR_MORE_DATA);
887 ret = FALSE;
889 else
891 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
892 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
893 pbEncoded += lenBytes;
894 if (pszObjId)
896 const char *ptr;
897 int val, pos;
899 *pbEncoded++ = firstByte;
900 ptr = pszObjId + firstPos;
901 while (ret && *ptr)
903 sscanf(ptr, "%d%n", &val, &pos);
905 unsigned char outBytes[5];
906 int numBytes, i;
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--)
920 outBytes[i - 1] = val & 0x7f;
921 val >>= 7;
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++;
934 *pcbEncoded = bytesNeeded;
935 return ret;
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)
942 BOOL ret = TRUE;
943 LPCSTR str = (LPCSTR)value->Value.pbData;
944 DWORD bytesNeeded, lenBytes, encodedLen;
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
953 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
954 pbEncoded, pcbEncoded, bytesNeeded)))
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);
964 return ret;
967 static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
968 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
969 DWORD *pcbEncoded)
971 BOOL ret = TRUE;
972 LPCWSTR str = (LPCWSTR)value->Value.pbData;
973 DWORD bytesNeeded, lenBytes, strLen;
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
987 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
988 pbEncoded, pcbEncoded, bytesNeeded)))
990 DWORD i;
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++)
999 *pbEncoded++ = (str[i] & 0xff00) >> 8;
1000 *pbEncoded++ = str[i] & 0x00ff;
1004 return ret;
1007 static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
1008 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1009 DWORD *pcbEncoded)
1011 BOOL ret = TRUE;
1012 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1013 DWORD bytesNeeded, lenBytes, encodedLen, strLen;
1015 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1016 strlenW(str);
1017 encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
1018 NULL);
1019 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1020 bytesNeeded = 1 + lenBytes + encodedLen;
1021 if (!pbEncoded)
1022 *pcbEncoded = bytesNeeded;
1023 else
1025 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1026 pbEncoded, pcbEncoded, bytesNeeded)))
1028 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1029 pbEncoded = *(BYTE **)pbEncoded;
1030 *pbEncoded++ = ASN_UTF8STRING;
1031 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
1032 pbEncoded += lenBytes;
1033 WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
1034 bytesNeeded - lenBytes - 1, NULL, NULL);
1037 return ret;
1040 static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
1041 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1042 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1044 BOOL ret = TRUE;
1046 __TRY
1048 const CERT_NAME_VALUE *value = pvStructInfo;
1050 switch (value->dwValueType)
1052 case CERT_RDN_ANY_TYPE:
1053 /* explicitly disallowed */
1054 SetLastError(E_INVALIDARG);
1055 ret = FALSE;
1056 break;
1057 case CERT_RDN_ENCODED_BLOB:
1058 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
1059 &value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1060 break;
1061 case CERT_RDN_OCTET_STRING:
1062 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
1063 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1064 break;
1065 case CERT_RDN_NUMERIC_STRING:
1066 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
1067 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1068 break;
1069 case CERT_RDN_PRINTABLE_STRING:
1070 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
1071 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1072 break;
1073 case CERT_RDN_TELETEX_STRING:
1074 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
1075 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1076 break;
1077 case CERT_RDN_VIDEOTEX_STRING:
1078 ret = CRYPT_AsnEncodeStringCoerce(value,
1079 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1080 break;
1081 case CERT_RDN_IA5_STRING:
1082 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
1083 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1084 break;
1085 case CERT_RDN_GRAPHIC_STRING:
1086 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
1087 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1088 break;
1089 case CERT_RDN_VISIBLE_STRING:
1090 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
1091 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1092 break;
1093 case CERT_RDN_GENERAL_STRING:
1094 ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
1095 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1096 break;
1097 case CERT_RDN_UNIVERSAL_STRING:
1098 FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
1099 SetLastError(CRYPT_E_ASN1_CHOICE);
1100 ret = FALSE;
1101 break;
1102 case CERT_RDN_BMP_STRING:
1103 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
1104 pbEncoded, pcbEncoded);
1105 break;
1106 case CERT_RDN_UTF8_STRING:
1107 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
1108 pbEncoded, pcbEncoded);
1109 break;
1110 default:
1111 SetLastError(CRYPT_E_ASN1_CHOICE);
1112 ret = FALSE;
1115 __EXCEPT_PAGE_FAULT
1117 SetLastError(STATUS_ACCESS_VIOLATION);
1118 ret = FALSE;
1120 __ENDTRY
1121 return ret;
1124 static BOOL CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
1125 const CERT_RDN_ATTR *attr, CryptEncodeObjectExFunc nameValueEncodeFunc,
1126 BYTE *pbEncoded, DWORD *pcbEncoded)
1128 DWORD bytesNeeded = 0, lenBytes, size;
1129 BOOL ret;
1131 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL, attr->pszObjId,
1132 0, NULL, NULL, &size);
1133 if (ret)
1135 bytesNeeded += size;
1136 /* hack: a CERT_RDN_ATTR is identical to a CERT_NAME_VALUE beginning
1137 * with dwValueType, so "cast" it to get its encoded size
1139 ret = nameValueEncodeFunc(dwCertEncodingType, NULL, &attr->dwValueType,
1140 0, NULL, NULL, &size);
1141 if (ret)
1143 bytesNeeded += size;
1144 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1145 bytesNeeded += 1 + lenBytes;
1146 if (pbEncoded)
1148 if (*pcbEncoded < bytesNeeded)
1150 SetLastError(ERROR_MORE_DATA);
1151 ret = FALSE;
1153 else
1155 *pbEncoded++ = ASN_SEQUENCE;
1156 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
1157 &lenBytes);
1158 pbEncoded += lenBytes;
1159 size = bytesNeeded - 1 - lenBytes;
1160 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
1161 attr->pszObjId, 0, NULL, pbEncoded, &size);
1162 if (ret)
1164 pbEncoded += size;
1165 size = bytesNeeded - 1 - lenBytes - size;
1166 ret = nameValueEncodeFunc(dwCertEncodingType, NULL,
1167 &attr->dwValueType, 0, NULL, pbEncoded, &size);
1168 if (!ret)
1169 *pcbEncoded = size;
1173 if (ret)
1174 *pcbEncoded = bytesNeeded;
1176 else
1178 /* Have to propagate index of failing character */
1179 *pcbEncoded = size;
1182 return ret;
1185 static int BLOBComp(const void *l, const void *r)
1187 const CRYPT_DER_BLOB *a = l, *b = r;
1188 int ret;
1190 if (!(ret = memcmp(a->pbData, b->pbData, min(a->cbData, b->cbData))))
1191 ret = a->cbData - b->cbData;
1192 return ret;
1195 /* This encodes a SET OF, which in DER must be lexicographically sorted.
1197 static BOOL WINAPI CRYPT_DEREncodeSet(DWORD dwCertEncodingType,
1198 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1199 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1201 const CRYPT_BLOB_ARRAY *set = pvStructInfo;
1202 DWORD bytesNeeded = 0, lenBytes, i;
1203 BOOL ret;
1205 for (i = 0; i < set->cBlob; i++)
1206 bytesNeeded += set->rgBlob[i].cbData;
1207 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1208 bytesNeeded += 1 + lenBytes;
1209 if (!pbEncoded)
1211 *pcbEncoded = bytesNeeded;
1212 ret = TRUE;
1214 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1215 pbEncoded, pcbEncoded, bytesNeeded)))
1217 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1218 pbEncoded = *(BYTE **)pbEncoded;
1219 qsort(set->rgBlob, set->cBlob, sizeof(CRYPT_DER_BLOB), BLOBComp);
1220 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1221 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1222 pbEncoded += lenBytes;
1223 for (i = 0; i < set->cBlob; i++)
1225 memcpy(pbEncoded, set->rgBlob[i].pbData, set->rgBlob[i].cbData);
1226 pbEncoded += set->rgBlob[i].cbData;
1229 return ret;
1232 struct DERSetDescriptor
1234 DWORD cItems;
1235 const void *items;
1236 size_t itemSize;
1237 size_t itemOffset;
1238 CryptEncodeObjectExFunc encode;
1241 static BOOL WINAPI CRYPT_DEREncodeItemsAsSet(DWORD dwCertEncodingType,
1242 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1243 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1245 const struct DERSetDescriptor *desc = pvStructInfo;
1246 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1247 BOOL ret = TRUE;
1248 DWORD i;
1250 if (desc->cItems)
1252 setOf.rgBlob = CryptMemAlloc(desc->cItems * sizeof(CRYPT_DER_BLOB));
1253 if (!setOf.rgBlob)
1254 ret = FALSE;
1255 else
1257 setOf.cBlob = desc->cItems;
1258 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1261 for (i = 0; ret && i < setOf.cBlob; i++)
1263 ret = desc->encode(dwCertEncodingType, lpszStructType,
1264 (const BYTE *)desc->items + i * desc->itemSize + desc->itemOffset,
1265 0, NULL, NULL, &setOf.rgBlob[i].cbData);
1266 if (ret)
1268 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1269 if (!setOf.rgBlob[i].pbData)
1270 ret = FALSE;
1271 else
1272 ret = desc->encode(dwCertEncodingType, lpszStructType,
1273 (const BYTE *)desc->items + i * desc->itemSize +
1274 desc->itemOffset, 0, NULL, setOf.rgBlob[i].pbData,
1275 &setOf.rgBlob[i].cbData);
1277 /* Some functions propagate their errors through the size */
1278 if (!ret)
1279 *pcbEncoded = setOf.rgBlob[i].cbData;
1281 if (ret)
1283 DWORD bytesNeeded = 0, lenBytes;
1285 for (i = 0; i < setOf.cBlob; i++)
1286 bytesNeeded += setOf.rgBlob[i].cbData;
1287 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1288 bytesNeeded += 1 + lenBytes;
1289 if (!pbEncoded)
1290 *pcbEncoded = bytesNeeded;
1291 else if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1292 pbEncoded, pcbEncoded, bytesNeeded)))
1294 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1295 pbEncoded = *(BYTE **)pbEncoded;
1296 qsort(setOf.rgBlob, setOf.cBlob, sizeof(CRYPT_DER_BLOB),
1297 BLOBComp);
1298 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
1299 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &lenBytes);
1300 pbEncoded += lenBytes;
1301 for (i = 0; i < setOf.cBlob; i++)
1303 memcpy(pbEncoded, setOf.rgBlob[i].pbData,
1304 setOf.rgBlob[i].cbData);
1305 pbEncoded += setOf.rgBlob[i].cbData;
1309 for (i = 0; i < setOf.cBlob; i++)
1310 CryptMemFree(setOf.rgBlob[i].pbData);
1311 CryptMemFree(setOf.rgBlob);
1312 return ret;
1315 static BOOL CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, const CERT_RDN *rdn,
1316 CryptEncodeObjectExFunc nameValueEncodeFunc, BYTE *pbEncoded,
1317 DWORD *pcbEncoded)
1319 BOOL ret;
1320 CRYPT_BLOB_ARRAY setOf = { 0, NULL };
1322 __TRY
1324 DWORD i;
1326 ret = TRUE;
1327 if (rdn->cRDNAttr)
1329 setOf.cBlob = rdn->cRDNAttr;
1330 setOf.rgBlob = CryptMemAlloc(rdn->cRDNAttr *
1331 sizeof(CRYPT_DER_BLOB));
1332 if (!setOf.rgBlob)
1333 ret = FALSE;
1334 else
1335 memset(setOf.rgBlob, 0, setOf.cBlob * sizeof(CRYPT_DER_BLOB));
1337 for (i = 0; ret && i < rdn->cRDNAttr; i++)
1339 setOf.rgBlob[i].cbData = 0;
1340 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
1341 nameValueEncodeFunc, NULL, &setOf.rgBlob[i].cbData);
1342 if (ret)
1344 setOf.rgBlob[i].pbData = CryptMemAlloc(setOf.rgBlob[i].cbData);
1345 if (!setOf.rgBlob[i].pbData)
1346 ret = FALSE;
1347 else
1348 ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
1349 &rdn->rgRDNAttr[i], nameValueEncodeFunc,
1350 setOf.rgBlob[i].pbData, &setOf.rgBlob[i].cbData);
1352 if (!ret)
1354 /* Have to propagate index of failing character */
1355 *pcbEncoded = setOf.rgBlob[i].cbData;
1358 if (ret)
1359 ret = CRYPT_DEREncodeSet(X509_ASN_ENCODING, NULL, &setOf, 0, NULL,
1360 pbEncoded, pcbEncoded);
1361 for (i = 0; i < setOf.cBlob; i++)
1362 CryptMemFree(setOf.rgBlob[i].pbData);
1364 __EXCEPT_PAGE_FAULT
1366 SetLastError(STATUS_ACCESS_VIOLATION);
1367 ret = FALSE;
1369 __ENDTRY
1370 CryptMemFree(setOf.rgBlob);
1371 return ret;
1374 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
1375 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1376 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
1378 static BOOL WINAPI CRYPT_AsnEncodeOrCopyUnicodeNameValue(
1379 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1380 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1381 DWORD *pcbEncoded)
1383 const CERT_NAME_VALUE *value = pvStructInfo;
1384 BOOL ret;
1386 if (value->dwValueType == CERT_RDN_ENCODED_BLOB)
1387 ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL, &value->Value,
1388 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1389 else
1390 ret = CRYPT_AsnEncodeUnicodeNameValue(dwCertEncodingType, NULL, value,
1391 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1392 return ret;
1395 static BOOL WINAPI CRYPT_AsnEncodeUnicodeName(DWORD dwCertEncodingType,
1396 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1397 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1399 BOOL ret = TRUE;
1401 __TRY
1403 const CERT_NAME_INFO *info = pvStructInfo;
1404 DWORD bytesNeeded = 0, lenBytes, size, i;
1406 TRACE("encoding name with %d RDNs\n", info->cRDN);
1407 ret = TRUE;
1408 for (i = 0; ret && i < info->cRDN; i++)
1410 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
1411 CRYPT_AsnEncodeOrCopyUnicodeNameValue, NULL, &size);
1412 if (ret)
1413 bytesNeeded += size;
1414 else
1415 *pcbEncoded = size;
1417 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
1418 bytesNeeded += 1 + lenBytes;
1419 if (ret)
1421 if (!pbEncoded)
1422 *pcbEncoded = bytesNeeded;
1423 else
1425 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1426 pbEncoded, pcbEncoded, bytesNeeded)))
1428 BYTE *out;
1430 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1431 pbEncoded = *(BYTE **)pbEncoded;
1432 out = pbEncoded;
1433 *out++ = ASN_SEQUENCEOF;
1434 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
1435 out += lenBytes;
1436 for (i = 0; ret && i < info->cRDN; i++)
1438 size = bytesNeeded;
1439 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
1440 &info->rgRDN[i], CRYPT_AsnEncodeOrCopyUnicodeNameValue,
1441 out, &size);
1442 if (ret)
1444 out += size;
1445 bytesNeeded -= size;
1447 else
1448 *pcbEncoded = size;
1450 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1451 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1456 __EXCEPT_PAGE_FAULT
1458 SetLastError(STATUS_ACCESS_VIOLATION);
1459 ret = FALSE;
1461 __ENDTRY
1462 return ret;
1465 static BOOL WINAPI CRYPT_AsnEncodeCTLVersion(DWORD dwCertEncodingType,
1466 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1467 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1469 const DWORD *ver = pvStructInfo;
1470 BOOL ret;
1472 /* CTL_V1 is not encoded */
1473 if (*ver == CTL_V1)
1475 *pcbEncoded = 0;
1476 ret = TRUE;
1478 else
1479 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, ver,
1480 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1481 return ret;
1484 /* Like CRYPT_AsnEncodeAlgorithmId, but encodes parameters as an asn.1 NULL
1485 * if they are empty and the OID is not empty (otherwise omits them.)
1487 static BOOL WINAPI CRYPT_AsnEncodeCTLSubjectAlgorithm(
1488 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1489 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1490 DWORD *pcbEncoded)
1492 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
1493 BOOL ret;
1494 struct AsnEncodeSequenceItem items[2] = {
1495 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
1497 DWORD cItem = 1;
1499 if (algo->pszObjId)
1501 static const BYTE asn1Null[] = { ASN_NULL, 0 };
1502 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
1503 (LPBYTE)asn1Null };
1505 if (algo->Parameters.cbData)
1506 items[cItem].pvStructInfo = &algo->Parameters;
1507 else
1508 items[cItem].pvStructInfo = &nullBlob;
1509 items[cItem].encodeFunc = CRYPT_CopyEncodedBlob;
1510 cItem++;
1512 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1513 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1514 return ret;
1517 static BOOL CRYPT_AsnEncodeCTLEntry(const CTL_ENTRY *entry,
1518 BYTE *pbEncoded, DWORD *pcbEncoded)
1520 struct AsnEncodeSequenceItem items[2] = {
1521 { &entry->SubjectIdentifier, CRYPT_AsnEncodeOctets, 0 },
1522 { &entry->cAttribute, CRYPT_AsnEncodePKCSAttributes, 0 },
1524 BOOL ret;
1526 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1527 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
1528 return ret;
1531 struct CTLEntries
1533 DWORD cEntry;
1534 CTL_ENTRY *rgEntry;
1537 static BOOL WINAPI CRYPT_AsnEncodeCTLEntries(DWORD dwCertEncodingType,
1538 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1539 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1541 BOOL ret;
1542 DWORD bytesNeeded, dataLen, lenBytes, i;
1543 const struct CTLEntries *entries = pvStructInfo;
1545 ret = TRUE;
1546 for (i = 0, dataLen = 0; ret && i < entries->cEntry; i++)
1548 DWORD size;
1550 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i], NULL, &size);
1551 if (ret)
1552 dataLen += size;
1554 if (ret)
1556 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1557 bytesNeeded = 1 + lenBytes + dataLen;
1558 if (!pbEncoded)
1559 *pcbEncoded = bytesNeeded;
1560 else
1562 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1563 pbEncoded, pcbEncoded, bytesNeeded)))
1565 BYTE *out;
1567 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1568 pbEncoded = *(BYTE **)pbEncoded;
1569 out = pbEncoded;
1570 *out++ = ASN_SEQUENCEOF;
1571 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1572 out += lenBytes;
1573 for (i = 0; ret && i < entries->cEntry; i++)
1575 DWORD size = dataLen;
1577 ret = CRYPT_AsnEncodeCTLEntry(&entries->rgEntry[i],
1578 out, &size);
1579 out += size;
1580 dataLen -= size;
1582 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1583 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1587 return ret;
1590 static BOOL WINAPI CRYPT_AsnEncodeCTL(DWORD dwCertEncodingType,
1591 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1592 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1594 BOOL ret = FALSE;
1596 __TRY
1598 const CTL_INFO *info = pvStructInfo;
1599 struct AsnEncodeSequenceItem items[9] = {
1600 { &info->dwVersion, CRYPT_AsnEncodeCTLVersion, 0 },
1601 { &info->SubjectUsage, CRYPT_AsnEncodeEnhancedKeyUsage, 0 },
1603 struct AsnConstructedItem constructed = { 0 };
1604 DWORD cItem = 2;
1606 if (info->ListIdentifier.cbData)
1608 items[cItem].pvStructInfo = &info->ListIdentifier;
1609 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
1610 cItem++;
1612 if (info->SequenceNumber.cbData)
1614 items[cItem].pvStructInfo = &info->SequenceNumber;
1615 items[cItem].encodeFunc = CRYPT_AsnEncodeInteger;
1616 cItem++;
1618 items[cItem].pvStructInfo = &info->ThisUpdate;
1619 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1620 cItem++;
1621 if (info->NextUpdate.dwLowDateTime || info->NextUpdate.dwHighDateTime)
1623 items[cItem].pvStructInfo = &info->NextUpdate;
1624 items[cItem].encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
1625 cItem++;
1627 items[cItem].pvStructInfo = &info->SubjectAlgorithm;
1628 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLSubjectAlgorithm;
1629 cItem++;
1630 if (info->cCTLEntry)
1632 items[cItem].pvStructInfo = &info->cCTLEntry;
1633 items[cItem].encodeFunc = CRYPT_AsnEncodeCTLEntries;
1634 cItem++;
1636 if (info->cExtension)
1638 constructed.tag = 0;
1639 constructed.pvStructInfo = &info->cExtension;
1640 constructed.encodeFunc = CRYPT_AsnEncodeExtensions;
1641 items[cItem].pvStructInfo = &constructed;
1642 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1643 cItem++;
1645 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1646 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1648 __EXCEPT_PAGE_FAULT
1650 SetLastError(STATUS_ACCESS_VIOLATION);
1652 __ENDTRY
1653 return ret;
1656 static BOOL CRYPT_AsnEncodeSMIMECapability(DWORD dwCertEncodingType,
1657 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1658 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1660 BOOL ret = FALSE;
1662 __TRY
1664 const CRYPT_SMIME_CAPABILITY *capability = pvStructInfo;
1666 if (!capability->pszObjId)
1667 SetLastError(E_INVALIDARG);
1668 else
1670 struct AsnEncodeSequenceItem items[] = {
1671 { capability->pszObjId, CRYPT_AsnEncodeOid, 0 },
1672 { &capability->Parameters, CRYPT_CopyEncodedBlob, 0 },
1675 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1676 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1677 pcbEncoded);
1680 __EXCEPT_PAGE_FAULT
1682 SetLastError(STATUS_ACCESS_VIOLATION);
1684 __ENDTRY
1685 return ret;
1688 static BOOL WINAPI CRYPT_AsnEncodeSMIMECapabilities(DWORD dwCertEncodingType,
1689 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1690 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1692 BOOL ret = FALSE;
1694 __TRY
1696 DWORD bytesNeeded, dataLen, lenBytes, i;
1697 const CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
1699 ret = TRUE;
1700 for (i = 0, dataLen = 0; ret && i < capabilities->cCapability; i++)
1702 DWORD size;
1704 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType, NULL,
1705 &capabilities->rgCapability[i], 0, NULL, NULL, &size);
1706 if (ret)
1707 dataLen += size;
1709 if (ret)
1711 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1712 bytesNeeded = 1 + lenBytes + dataLen;
1713 if (!pbEncoded)
1714 *pcbEncoded = bytesNeeded;
1715 else
1717 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
1718 pbEncoded, pcbEncoded, bytesNeeded)))
1720 BYTE *out;
1722 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1723 pbEncoded = *(BYTE **)pbEncoded;
1724 out = pbEncoded;
1725 *out++ = ASN_SEQUENCEOF;
1726 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1727 out += lenBytes;
1728 for (i = 0; i < capabilities->cCapability; i++)
1730 DWORD size = dataLen;
1732 ret = CRYPT_AsnEncodeSMIMECapability(dwCertEncodingType,
1733 NULL, &capabilities->rgCapability[i], 0, NULL,
1734 out, &size);
1735 out += size;
1736 dataLen -= size;
1738 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1739 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1744 __EXCEPT_PAGE_FAULT
1746 SetLastError(STATUS_ACCESS_VIOLATION);
1748 __ENDTRY
1749 return ret;
1752 static BOOL WINAPI CRYPT_AsnEncodeNoticeNumbers(DWORD dwCertEncodingType,
1753 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1754 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1756 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1757 DWORD bytesNeeded, dataLen, lenBytes, i;
1758 BOOL ret = TRUE;
1760 for (i = 0, dataLen = 0; ret && i < noticeRef->cNoticeNumbers; i++)
1762 DWORD size;
1764 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1765 &noticeRef->rgNoticeNumbers[i], 0, NULL, NULL, &size);
1766 if (ret)
1767 dataLen += size;
1769 if (ret)
1771 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
1772 bytesNeeded = 1 + lenBytes + dataLen;
1773 if (!pbEncoded)
1774 *pcbEncoded = bytesNeeded;
1775 else
1777 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
1778 pcbEncoded, bytesNeeded)))
1780 BYTE *out;
1782 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
1783 pbEncoded = *(BYTE **)pbEncoded;
1784 out = pbEncoded;
1785 *out++ = ASN_SEQUENCE;
1786 CRYPT_EncodeLen(dataLen, out, &lenBytes);
1787 out += lenBytes;
1788 for (i = 0; i < noticeRef->cNoticeNumbers; i++)
1790 DWORD size = dataLen;
1792 ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
1793 &noticeRef->rgNoticeNumbers[i], 0, NULL, out, &size);
1794 out += size;
1795 dataLen -= size;
1797 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
1798 CRYPT_FreeSpace(pEncodePara, pbEncoded);
1802 return ret;
1805 static BOOL WINAPI CRYPT_AsnEncodeNoticeReference(DWORD dwCertEncodingType,
1806 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1807 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1809 const CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *noticeRef = pvStructInfo;
1810 BOOL ret;
1811 CERT_NAME_VALUE orgValue = { CERT_RDN_IA5_STRING,
1812 { 0, (LPBYTE)noticeRef->pszOrganization } };
1813 struct AsnEncodeSequenceItem items[] = {
1814 { &orgValue, CRYPT_AsnEncodeNameValue, 0 },
1815 { noticeRef, CRYPT_AsnEncodeNoticeNumbers, 0 },
1818 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1819 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1820 pcbEncoded);
1821 return ret;
1824 static BOOL WINAPI CRYPT_AsnEncodePolicyQualifierUserNotice(
1825 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1826 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1827 DWORD *pcbEncoded)
1829 BOOL ret = FALSE;
1831 __TRY
1833 const CERT_POLICY_QUALIFIER_USER_NOTICE *notice = pvStructInfo;
1834 struct AsnEncodeSequenceItem items[2];
1835 CERT_NAME_VALUE displayTextValue;
1836 DWORD cItem = 0;
1838 ret = TRUE;
1839 if (notice->pNoticeReference)
1841 items[cItem].encodeFunc = CRYPT_AsnEncodeNoticeReference;
1842 items[cItem].pvStructInfo = notice->pNoticeReference;
1843 cItem++;
1845 if (notice->pszDisplayText)
1847 displayTextValue.dwValueType = CERT_RDN_BMP_STRING;
1848 displayTextValue.Value.cbData = 0;
1849 displayTextValue.Value.pbData = (LPBYTE)notice->pszDisplayText;
1850 items[cItem].encodeFunc = CRYPT_AsnEncodeNameValue;
1851 items[cItem].pvStructInfo = &displayTextValue;
1852 cItem++;
1854 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
1855 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1857 __EXCEPT_PAGE_FAULT
1859 SetLastError(STATUS_ACCESS_VIOLATION);
1861 __ENDTRY
1862 return ret;
1865 static BOOL WINAPI CRYPT_AsnEncodePKCSAttribute(DWORD dwCertEncodingType,
1866 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1867 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1869 BOOL ret = FALSE;
1871 __TRY
1873 const CRYPT_ATTRIBUTE *attr = pvStructInfo;
1875 if (!attr->pszObjId)
1876 SetLastError(E_INVALIDARG);
1877 else
1879 struct AsnEncodeSequenceItem items[2] = {
1880 { attr->pszObjId, CRYPT_AsnEncodeOid, 0 },
1881 { &attr->cValue, CRYPT_DEREncodeSet, 0 },
1884 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1885 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
1886 pcbEncoded);
1889 __EXCEPT_PAGE_FAULT
1891 SetLastError(STATUS_ACCESS_VIOLATION);
1893 __ENDTRY
1894 return ret;
1897 static BOOL WINAPI CRYPT_AsnEncodePKCSAttributes(DWORD dwCertEncodingType,
1898 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1899 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1901 BOOL ret = FALSE;
1903 __TRY
1905 const CRYPT_ATTRIBUTES *attributes = pvStructInfo;
1906 struct DERSetDescriptor desc = { attributes->cAttr, attributes->rgAttr,
1907 sizeof(CRYPT_ATTRIBUTE), 0, CRYPT_AsnEncodePKCSAttribute };
1909 ret = CRYPT_DEREncodeItemsAsSet(X509_ASN_ENCODING, lpszStructType,
1910 &desc, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1912 __EXCEPT_PAGE_FAULT
1914 SetLastError(STATUS_ACCESS_VIOLATION);
1916 __ENDTRY
1917 return ret;
1920 /* Like CRYPT_AsnEncodePKCSContentInfo, but allows the OID to be NULL */
1921 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfoInternal(
1922 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
1923 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
1924 DWORD *pcbEncoded)
1926 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1927 struct AsnEncodeSequenceItem items[2] = {
1928 { info->pszObjId, CRYPT_AsnEncodeOid, 0 },
1929 { NULL, NULL, 0 },
1931 struct AsnConstructedItem constructed = { 0 };
1932 DWORD cItem = 1;
1934 if (info->Content.cbData)
1936 constructed.tag = 0;
1937 constructed.pvStructInfo = &info->Content;
1938 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
1939 items[cItem].pvStructInfo = &constructed;
1940 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
1941 cItem++;
1943 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
1944 cItem, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
1947 BOOL CRYPT_AsnEncodePKCSDigestedData(const CRYPT_DIGESTED_DATA *digestedData,
1948 void *pvData, DWORD *pcbData)
1950 struct AsnEncodeSequenceItem items[] = {
1951 { &digestedData->version, CRYPT_AsnEncodeInt, 0 },
1952 { &digestedData->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
1953 0 },
1954 { &digestedData->ContentInfo, CRYPT_AsnEncodePKCSContentInfoInternal, 0 },
1955 { &digestedData->hash, CRYPT_AsnEncodeOctets, 0 },
1958 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
1959 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
1962 static BOOL WINAPI CRYPT_AsnEncodePKCSContentInfo(DWORD dwCertEncodingType,
1963 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
1964 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
1966 BOOL ret = FALSE;
1968 __TRY
1970 const CRYPT_CONTENT_INFO *info = pvStructInfo;
1972 if (!info->pszObjId)
1973 SetLastError(E_INVALIDARG);
1974 else
1975 ret = CRYPT_AsnEncodePKCSContentInfoInternal(dwCertEncodingType,
1976 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
1977 pcbEncoded);
1979 __EXCEPT_PAGE_FAULT
1981 SetLastError(STATUS_ACCESS_VIOLATION);
1983 __ENDTRY
1984 return ret;
1987 static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
1988 BYTE tag, DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
1989 DWORD *pcbEncoded)
1991 BOOL ret = TRUE;
1992 LPCWSTR str = (LPCWSTR)value->Value.pbData;
1993 DWORD bytesNeeded, lenBytes, encodedLen;
1995 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
1996 strlenW(str);
1997 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
1998 bytesNeeded = 1 + lenBytes + encodedLen;
1999 if (!pbEncoded)
2000 *pcbEncoded = bytesNeeded;
2001 else
2003 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2004 pbEncoded, pcbEncoded, bytesNeeded)))
2006 DWORD i;
2008 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2009 pbEncoded = *(BYTE **)pbEncoded;
2010 *pbEncoded++ = tag;
2011 CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
2012 pbEncoded += lenBytes;
2013 for (i = 0; i < encodedLen; i++)
2014 *pbEncoded++ = (BYTE)str[i];
2017 return ret;
2020 static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
2021 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2022 DWORD *pcbEncoded)
2024 BOOL ret = TRUE;
2025 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2026 DWORD bytesNeeded, lenBytes, encodedLen;
2028 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2029 strlenW(str);
2030 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2031 bytesNeeded = 1 + lenBytes + encodedLen;
2032 if (!pbEncoded)
2033 *pcbEncoded = bytesNeeded;
2034 else
2036 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2037 pbEncoded, pcbEncoded, bytesNeeded)))
2039 DWORD i;
2040 BYTE *ptr;
2042 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2043 ptr = *(BYTE **)pbEncoded;
2044 else
2045 ptr = pbEncoded;
2046 *ptr++ = ASN_NUMERICSTRING;
2047 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2048 ptr += lenBytes;
2049 for (i = 0; ret && i < encodedLen; i++)
2051 if (isdigitW(str[i]))
2052 *ptr++ = (BYTE)str[i];
2053 else
2055 *pcbEncoded = i;
2056 SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
2057 ret = FALSE;
2060 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2061 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2064 return ret;
2067 static inline int isprintableW(WCHAR wc)
2069 return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
2070 wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
2071 wc == '/' || wc == ':' || wc == '=' || wc == '?';
2074 static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
2075 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2076 DWORD *pcbEncoded)
2078 BOOL ret = TRUE;
2079 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2080 DWORD bytesNeeded, lenBytes, encodedLen;
2082 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2083 strlenW(str);
2084 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2085 bytesNeeded = 1 + lenBytes + encodedLen;
2086 if (!pbEncoded)
2087 *pcbEncoded = bytesNeeded;
2088 else
2090 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2091 pbEncoded, pcbEncoded, bytesNeeded)))
2093 DWORD i;
2094 BYTE *ptr;
2096 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2097 ptr = *(BYTE **)pbEncoded;
2098 else
2099 ptr = pbEncoded;
2100 *ptr++ = ASN_PRINTABLESTRING;
2101 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2102 ptr += lenBytes;
2103 for (i = 0; ret && i < encodedLen; i++)
2105 if (isprintableW(str[i]))
2106 *ptr++ = (BYTE)str[i];
2107 else
2109 *pcbEncoded = i;
2110 SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
2111 ret = FALSE;
2114 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2115 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2118 return ret;
2121 static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
2122 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2123 DWORD *pcbEncoded)
2125 BOOL ret = TRUE;
2126 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2127 DWORD bytesNeeded, lenBytes, encodedLen;
2129 encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2130 strlenW(str);
2131 CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
2132 bytesNeeded = 1 + lenBytes + encodedLen;
2133 if (!pbEncoded)
2134 *pcbEncoded = bytesNeeded;
2135 else
2137 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2138 pbEncoded, pcbEncoded, bytesNeeded)))
2140 DWORD i;
2141 BYTE *ptr;
2143 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2144 ptr = *(BYTE **)pbEncoded;
2145 else
2146 ptr = pbEncoded;
2147 *ptr++ = ASN_IA5STRING;
2148 CRYPT_EncodeLen(encodedLen, ptr, &lenBytes);
2149 ptr += lenBytes;
2150 for (i = 0; ret && i < encodedLen; i++)
2152 if (str[i] <= 0x7f)
2153 *ptr++ = (BYTE)str[i];
2154 else
2156 *pcbEncoded = i;
2157 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2158 ret = FALSE;
2161 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2162 CRYPT_FreeSpace(pEncodePara, *(BYTE **)pbEncoded);
2165 return ret;
2168 static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
2169 DWORD dwFlags, const CRYPT_ENCODE_PARA *pEncodePara, BYTE *pbEncoded,
2170 DWORD *pcbEncoded)
2172 BOOL ret = TRUE;
2173 LPCWSTR str = (LPCWSTR)value->Value.pbData;
2174 DWORD bytesNeeded, lenBytes, strLen;
2176 /* FIXME: doesn't handle composite characters */
2177 strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
2178 strlenW(str);
2179 CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
2180 bytesNeeded = 1 + lenBytes + strLen * 4;
2181 if (!pbEncoded)
2182 *pcbEncoded = bytesNeeded;
2183 else
2185 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2186 pbEncoded, pcbEncoded, bytesNeeded)))
2188 DWORD i;
2190 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2191 pbEncoded = *(BYTE **)pbEncoded;
2192 *pbEncoded++ = ASN_UNIVERSALSTRING;
2193 CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
2194 pbEncoded += lenBytes;
2195 for (i = 0; i < strLen; i++)
2197 *pbEncoded++ = 0;
2198 *pbEncoded++ = 0;
2199 *pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
2200 *pbEncoded++ = (BYTE)(str[i] & 0x00ff);
2204 return ret;
2207 static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
2208 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2209 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2211 BOOL ret = FALSE;
2213 __TRY
2215 const CERT_NAME_VALUE *value = pvStructInfo;
2217 switch (value->dwValueType)
2219 case CERT_RDN_ANY_TYPE:
2220 case CERT_RDN_ENCODED_BLOB:
2221 case CERT_RDN_OCTET_STRING:
2222 SetLastError(CRYPT_E_NOT_CHAR_STRING);
2223 break;
2224 case CERT_RDN_NUMERIC_STRING:
2225 ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
2226 pbEncoded, pcbEncoded);
2227 break;
2228 case CERT_RDN_PRINTABLE_STRING:
2229 ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
2230 pbEncoded, pcbEncoded);
2231 break;
2232 case CERT_RDN_TELETEX_STRING:
2233 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
2234 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2235 break;
2236 case CERT_RDN_VIDEOTEX_STRING:
2237 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
2238 ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2239 break;
2240 case CERT_RDN_IA5_STRING:
2241 ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
2242 pbEncoded, pcbEncoded);
2243 break;
2244 case CERT_RDN_GRAPHIC_STRING:
2245 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
2246 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2247 break;
2248 case CERT_RDN_VISIBLE_STRING:
2249 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
2250 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2251 break;
2252 case CERT_RDN_GENERAL_STRING:
2253 ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
2254 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2255 break;
2256 case CERT_RDN_UNIVERSAL_STRING:
2257 ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
2258 pbEncoded, pcbEncoded);
2259 break;
2260 case CERT_RDN_BMP_STRING:
2261 ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
2262 pbEncoded, pcbEncoded);
2263 break;
2264 case CERT_RDN_UTF8_STRING:
2265 ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
2266 pbEncoded, pcbEncoded);
2267 break;
2268 default:
2269 SetLastError(CRYPT_E_ASN1_CHOICE);
2272 __EXCEPT_PAGE_FAULT
2274 SetLastError(STATUS_ACCESS_VIOLATION);
2276 __ENDTRY
2277 return ret;
2280 static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
2281 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2282 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2284 BOOL ret;
2286 __TRY
2288 const CERT_NAME_INFO *info = pvStructInfo;
2289 DWORD bytesNeeded = 0, lenBytes, size, i;
2291 TRACE("encoding name with %d RDNs\n", info->cRDN);
2292 ret = TRUE;
2293 for (i = 0; ret && i < info->cRDN; i++)
2295 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i],
2296 CRYPT_AsnEncodeNameValue, NULL, &size);
2297 if (ret)
2298 bytesNeeded += size;
2300 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2301 bytesNeeded += 1 + lenBytes;
2302 if (ret)
2304 if (!pbEncoded)
2305 *pcbEncoded = bytesNeeded;
2306 else
2308 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2309 pbEncoded, pcbEncoded, bytesNeeded)))
2311 BYTE *out;
2313 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2314 pbEncoded = *(BYTE **)pbEncoded;
2315 out = pbEncoded;
2316 *out++ = ASN_SEQUENCEOF;
2317 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2318 out += lenBytes;
2319 for (i = 0; ret && i < info->cRDN; i++)
2321 size = bytesNeeded;
2322 ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
2323 &info->rgRDN[i], CRYPT_AsnEncodeNameValue, out, &size);
2324 if (ret)
2326 out += size;
2327 bytesNeeded -= size;
2330 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2331 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2336 __EXCEPT_PAGE_FAULT
2338 SetLastError(STATUS_ACCESS_VIOLATION);
2339 ret = FALSE;
2341 __ENDTRY
2342 return ret;
2345 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
2346 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2347 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2349 BOOL val = *(const BOOL *)pvStructInfo, ret;
2351 TRACE("%d\n", val);
2353 if (!pbEncoded)
2355 *pcbEncoded = 3;
2356 ret = TRUE;
2358 else if (*pcbEncoded < 3)
2360 *pcbEncoded = 3;
2361 SetLastError(ERROR_MORE_DATA);
2362 ret = FALSE;
2364 else
2366 *pcbEncoded = 3;
2367 *pbEncoded++ = ASN_BOOL;
2368 *pbEncoded++ = 1;
2369 *pbEncoded++ = val ? 0xff : 0;
2370 ret = TRUE;
2372 TRACE("returning %d (%08x)\n", ret, GetLastError());
2373 return ret;
2376 static BOOL WINAPI CRYPT_AsnEncodeAltNameEntry(DWORD dwCertEncodingType,
2377 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2378 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2380 const CERT_ALT_NAME_ENTRY *entry = pvStructInfo;
2381 BOOL ret;
2382 DWORD dataLen;
2383 BYTE tag;
2385 ret = TRUE;
2386 switch (entry->dwAltNameChoice)
2388 case CERT_ALT_NAME_RFC822_NAME:
2389 case CERT_ALT_NAME_DNS_NAME:
2390 case CERT_ALT_NAME_URL:
2391 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2392 if (entry->u.pwszURL)
2394 DWORD i;
2396 /* Not + 1: don't encode the NULL-terminator */
2397 dataLen = lstrlenW(entry->u.pwszURL);
2398 for (i = 0; ret && i < dataLen; i++)
2400 if (entry->u.pwszURL[i] > 0x7f)
2402 SetLastError(CRYPT_E_INVALID_IA5_STRING);
2403 ret = FALSE;
2404 *pcbEncoded = i;
2408 else
2409 dataLen = 0;
2410 break;
2411 case CERT_ALT_NAME_DIRECTORY_NAME:
2412 tag = ASN_CONTEXT | ASN_CONSTRUCTOR | (entry->dwAltNameChoice - 1);
2413 dataLen = entry->u.DirectoryName.cbData;
2414 break;
2415 case CERT_ALT_NAME_IP_ADDRESS:
2416 tag = ASN_CONTEXT | (entry->dwAltNameChoice - 1);
2417 dataLen = entry->u.IPAddress.cbData;
2418 break;
2419 case CERT_ALT_NAME_REGISTERED_ID:
2421 struct AsnEncodeTagSwappedItem swapped =
2422 { ASN_CONTEXT | (entry->dwAltNameChoice - 1), entry->u.pszRegisteredID,
2423 CRYPT_AsnEncodeOid };
2425 return CRYPT_AsnEncodeSwapTag(0, NULL, &swapped, 0, NULL, pbEncoded,
2426 pcbEncoded);
2428 case CERT_ALT_NAME_OTHER_NAME:
2429 FIXME("name type %d unimplemented\n", entry->dwAltNameChoice);
2430 return FALSE;
2431 default:
2432 SetLastError(E_INVALIDARG);
2433 return FALSE;
2435 if (ret)
2437 DWORD bytesNeeded, lenBytes;
2439 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2440 bytesNeeded = 1 + dataLen + lenBytes;
2441 if (!pbEncoded)
2442 *pcbEncoded = bytesNeeded;
2443 else if (*pcbEncoded < bytesNeeded)
2445 SetLastError(ERROR_MORE_DATA);
2446 *pcbEncoded = bytesNeeded;
2447 ret = FALSE;
2449 else
2451 *pbEncoded++ = tag;
2452 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
2453 pbEncoded += lenBytes;
2454 switch (entry->dwAltNameChoice)
2456 case CERT_ALT_NAME_RFC822_NAME:
2457 case CERT_ALT_NAME_DNS_NAME:
2458 case CERT_ALT_NAME_URL:
2460 DWORD i;
2462 for (i = 0; i < dataLen; i++)
2463 *pbEncoded++ = (BYTE)entry->u.pwszURL[i];
2464 break;
2466 case CERT_ALT_NAME_DIRECTORY_NAME:
2467 memcpy(pbEncoded, entry->u.DirectoryName.pbData, dataLen);
2468 break;
2469 case CERT_ALT_NAME_IP_ADDRESS:
2470 memcpy(pbEncoded, entry->u.IPAddress.pbData, dataLen);
2471 break;
2473 if (ret)
2474 *pcbEncoded = bytesNeeded;
2477 TRACE("returning %d (%08x)\n", ret, GetLastError());
2478 return ret;
2481 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId(DWORD dwCertEncodingType,
2482 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2483 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2485 BOOL ret;
2487 __TRY
2489 const CERT_AUTHORITY_KEY_ID_INFO *info = pvStructInfo;
2490 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2491 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2492 struct AsnConstructedItem constructed = { 0 };
2493 DWORD cItem = 0, cSwapped = 0;
2495 if (info->KeyId.cbData)
2497 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2498 swapped[cSwapped].pvStructInfo = &info->KeyId;
2499 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2500 items[cItem].pvStructInfo = &swapped[cSwapped];
2501 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2502 cSwapped++;
2503 cItem++;
2505 if (info->CertIssuer.cbData)
2507 constructed.tag = 1;
2508 constructed.pvStructInfo = &info->CertIssuer;
2509 constructed.encodeFunc = CRYPT_CopyEncodedBlob;
2510 items[cItem].pvStructInfo = &constructed;
2511 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
2512 cItem++;
2514 if (info->CertSerialNumber.cbData)
2516 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2517 swapped[cSwapped].pvStructInfo = &info->CertSerialNumber;
2518 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2519 items[cItem].pvStructInfo = &swapped[cSwapped];
2520 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2521 cSwapped++;
2522 cItem++;
2524 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2525 pEncodePara, pbEncoded, pcbEncoded);
2527 __EXCEPT_PAGE_FAULT
2529 SetLastError(STATUS_ACCESS_VIOLATION);
2530 ret = FALSE;
2532 __ENDTRY
2533 return ret;
2536 static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
2537 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2538 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2540 BOOL ret;
2542 __TRY
2544 const CERT_ALT_NAME_INFO *info = pvStructInfo;
2545 DWORD bytesNeeded, dataLen, lenBytes, i;
2547 ret = TRUE;
2548 /* FIXME: should check that cAltEntry is not bigger than 0xff, since we
2549 * can't encode an erroneous entry index if it's bigger than this.
2551 for (i = 0, dataLen = 0; ret && i < info->cAltEntry; i++)
2553 DWORD len;
2555 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType, NULL,
2556 &info->rgAltEntry[i], 0, NULL, NULL, &len);
2557 if (ret)
2558 dataLen += len;
2559 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
2561 /* CRYPT_AsnEncodeAltNameEntry encoded the index of
2562 * the bad character, now set the index of the bad
2563 * entry
2565 *pcbEncoded = (BYTE)i <<
2566 CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT | len;
2569 if (ret)
2571 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2572 bytesNeeded = 1 + lenBytes + dataLen;
2573 if (!pbEncoded)
2575 *pcbEncoded = bytesNeeded;
2576 ret = TRUE;
2578 else
2580 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2581 pbEncoded, pcbEncoded, bytesNeeded)))
2583 BYTE *out;
2585 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2586 pbEncoded = *(BYTE **)pbEncoded;
2587 out = pbEncoded;
2588 *out++ = ASN_SEQUENCEOF;
2589 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2590 out += lenBytes;
2591 for (i = 0; ret && i < info->cAltEntry; i++)
2593 DWORD len = dataLen;
2595 ret = CRYPT_AsnEncodeAltNameEntry(dwCertEncodingType,
2596 NULL, &info->rgAltEntry[i], 0, NULL, out, &len);
2597 if (ret)
2599 out += len;
2600 dataLen -= len;
2603 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2604 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2609 __EXCEPT_PAGE_FAULT
2611 SetLastError(STATUS_ACCESS_VIOLATION);
2612 ret = FALSE;
2614 __ENDTRY
2615 return ret;
2618 static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
2619 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2620 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2622 BOOL ret;
2624 __TRY
2626 const CERT_AUTHORITY_KEY_ID2_INFO *info = pvStructInfo;
2627 struct AsnEncodeSequenceItem items[3] = { { 0 } };
2628 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
2629 DWORD cItem = 0, cSwapped = 0;
2631 if (info->KeyId.cbData)
2633 swapped[cSwapped].tag = ASN_CONTEXT | 0;
2634 swapped[cSwapped].pvStructInfo = &info->KeyId;
2635 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
2636 items[cItem].pvStructInfo = &swapped[cSwapped];
2637 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2638 cSwapped++;
2639 cItem++;
2641 if (info->AuthorityCertIssuer.cAltEntry)
2643 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
2644 swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
2645 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
2646 items[cItem].pvStructInfo = &swapped[cSwapped];
2647 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2648 cSwapped++;
2649 cItem++;
2651 if (info->AuthorityCertSerialNumber.cbData)
2653 swapped[cSwapped].tag = ASN_CONTEXT | 2;
2654 swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
2655 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
2656 items[cItem].pvStructInfo = &swapped[cSwapped];
2657 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
2658 cSwapped++;
2659 cItem++;
2661 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
2662 pEncodePara, pbEncoded, pcbEncoded);
2664 __EXCEPT_PAGE_FAULT
2666 SetLastError(STATUS_ACCESS_VIOLATION);
2667 ret = FALSE;
2669 __ENDTRY
2670 return ret;
2673 static BOOL CRYPT_AsnEncodeAccessDescription(
2674 const CERT_ACCESS_DESCRIPTION *descr, BYTE *pbEncoded, DWORD *pcbEncoded)
2676 struct AsnEncodeSequenceItem items[] = {
2677 { descr->pszAccessMethod, CRYPT_AsnEncodeOid, 0 },
2678 { &descr->AccessLocation, CRYPT_AsnEncodeAltNameEntry, 0 },
2681 if (!descr->pszAccessMethod)
2683 SetLastError(E_INVALIDARG);
2684 return FALSE;
2686 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
2687 sizeof(items) / sizeof(items[0]), 0, NULL, pbEncoded, pcbEncoded);
2690 static BOOL WINAPI CRYPT_AsnEncodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2691 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2692 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2694 BOOL ret;
2696 __TRY
2698 DWORD bytesNeeded, dataLen, lenBytes, i;
2699 const CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
2701 ret = TRUE;
2702 for (i = 0, dataLen = 0; ret && i < info->cAccDescr; i++)
2704 DWORD size;
2706 ret = CRYPT_AsnEncodeAccessDescription(&info->rgAccDescr[i], NULL,
2707 &size);
2708 if (ret)
2709 dataLen += size;
2711 if (ret)
2713 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
2714 bytesNeeded = 1 + lenBytes + dataLen;
2715 if (!pbEncoded)
2716 *pcbEncoded = bytesNeeded;
2717 else
2719 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2720 pbEncoded, pcbEncoded, bytesNeeded)))
2722 BYTE *out;
2724 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2725 pbEncoded = *(BYTE **)pbEncoded;
2726 out = pbEncoded;
2727 *out++ = ASN_SEQUENCEOF;
2728 CRYPT_EncodeLen(dataLen, out, &lenBytes);
2729 out += lenBytes;
2730 for (i = 0; i < info->cAccDescr; i++)
2732 DWORD size = dataLen;
2734 ret = CRYPT_AsnEncodeAccessDescription(
2735 &info->rgAccDescr[i], out, &size);
2736 out += size;
2737 dataLen -= size;
2739 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2740 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2745 __EXCEPT_PAGE_FAULT
2747 SetLastError(STATUS_ACCESS_VIOLATION);
2748 ret = FALSE;
2750 __ENDTRY
2751 return ret;
2754 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
2755 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2756 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2758 BOOL ret;
2760 __TRY
2762 const CERT_BASIC_CONSTRAINTS_INFO *info = pvStructInfo;
2763 struct AsnEncodeSequenceItem items[3] = {
2764 { &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
2765 { 0 }
2767 DWORD cItem = 1;
2769 if (info->fPathLenConstraint)
2771 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2772 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2773 cItem++;
2775 if (info->cSubtreesConstraint)
2777 items[cItem].pvStructInfo = &info->cSubtreesConstraint;
2778 items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
2779 cItem++;
2781 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2782 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2784 __EXCEPT_PAGE_FAULT
2786 SetLastError(STATUS_ACCESS_VIOLATION);
2787 ret = FALSE;
2789 __ENDTRY
2790 return ret;
2793 static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
2794 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2795 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2797 BOOL ret;
2799 __TRY
2801 const CERT_BASIC_CONSTRAINTS2_INFO *info = pvStructInfo;
2802 struct AsnEncodeSequenceItem items[2] = { { 0 } };
2803 DWORD cItem = 0;
2805 if (info->fCA)
2807 items[cItem].pvStructInfo = &info->fCA;
2808 items[cItem].encodeFunc = CRYPT_AsnEncodeBool;
2809 cItem++;
2811 if (info->fPathLenConstraint)
2813 items[cItem].pvStructInfo = &info->dwPathLenConstraint;
2814 items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
2815 cItem++;
2817 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
2818 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
2820 __EXCEPT_PAGE_FAULT
2822 SetLastError(STATUS_ACCESS_VIOLATION);
2823 ret = FALSE;
2825 __ENDTRY
2826 return ret;
2829 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyQualifiers(DWORD dwCertEncodingType,
2830 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2831 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2833 const CERT_POLICY_INFO *info = pvStructInfo;
2834 BOOL ret;
2836 if (!info->cPolicyQualifier)
2838 *pcbEncoded = 0;
2839 ret = TRUE;
2841 else
2843 struct AsnEncodeSequenceItem items[2] = {
2844 { NULL, CRYPT_AsnEncodeOid, 0 },
2845 { NULL, CRYPT_CopyEncodedBlob, 0 },
2847 DWORD bytesNeeded = 0, lenBytes, size, i;
2849 ret = TRUE;
2850 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2852 items[0].pvStructInfo =
2853 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2854 items[1].pvStructInfo = &info->rgPolicyQualifier[i].Qualifier;
2855 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2856 sizeof(items) / sizeof(items[0]),
2857 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
2858 if (ret)
2859 bytesNeeded += size;
2861 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2862 bytesNeeded += 1 + lenBytes;
2863 if (ret)
2865 if (!pbEncoded)
2866 *pcbEncoded = bytesNeeded;
2867 else
2869 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2870 pbEncoded, pcbEncoded, bytesNeeded)))
2872 BYTE *out;
2874 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2875 pbEncoded = *(BYTE **)pbEncoded;
2876 out = pbEncoded;
2877 *out++ = ASN_SEQUENCEOF;
2878 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2879 out += lenBytes;
2880 for (i = 0; ret && i < info->cPolicyQualifier; i++)
2882 items[0].pvStructInfo =
2883 info->rgPolicyQualifier[i].pszPolicyQualifierId;
2884 items[1].pvStructInfo =
2885 &info->rgPolicyQualifier[i].Qualifier;
2886 size = bytesNeeded;
2887 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2888 sizeof(items) / sizeof(items[0]),
2889 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
2890 if (ret)
2892 out += size;
2893 bytesNeeded -= size;
2896 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2897 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2902 return ret;
2905 static BOOL CRYPT_AsnEncodeCertPolicy(DWORD dwCertEncodingType,
2906 const CERT_POLICY_INFO *info, DWORD dwFlags, BYTE *pbEncoded,
2907 DWORD *pcbEncoded)
2909 struct AsnEncodeSequenceItem items[2] = {
2910 { info->pszPolicyIdentifier, CRYPT_AsnEncodeOid, 0 },
2911 { info, CRYPT_AsnEncodeCertPolicyQualifiers, 0 },
2913 BOOL ret;
2915 if (!info->pszPolicyIdentifier)
2917 SetLastError(E_INVALIDARG);
2918 return FALSE;
2920 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
2921 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
2922 return ret;
2925 static BOOL WINAPI CRYPT_AsnEncodeCertPolicies(DWORD dwCertEncodingType,
2926 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
2927 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
2929 BOOL ret = FALSE;
2931 __TRY
2933 const CERT_POLICIES_INFO *info = pvStructInfo;
2934 DWORD bytesNeeded = 0, lenBytes, size, i;
2936 ret = TRUE;
2937 for (i = 0; ret && i < info->cPolicyInfo; i++)
2939 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2940 &info->rgPolicyInfo[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL,
2941 &size);
2942 if (ret)
2943 bytesNeeded += size;
2945 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
2946 bytesNeeded += 1 + lenBytes;
2947 if (ret)
2949 if (!pbEncoded)
2950 *pcbEncoded = bytesNeeded;
2951 else
2953 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
2954 pbEncoded, pcbEncoded, bytesNeeded)))
2956 BYTE *out;
2958 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
2959 pbEncoded = *(BYTE **)pbEncoded;
2960 out = pbEncoded;
2961 *out++ = ASN_SEQUENCEOF;
2962 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
2963 out += lenBytes;
2964 for (i = 0; ret && i < info->cPolicyInfo; i++)
2966 size = bytesNeeded;
2967 ret = CRYPT_AsnEncodeCertPolicy(dwCertEncodingType,
2968 &info->rgPolicyInfo[i],
2969 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
2970 if (ret)
2972 out += size;
2973 bytesNeeded -= size;
2976 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
2977 CRYPT_FreeSpace(pEncodePara, pbEncoded);
2982 __EXCEPT_PAGE_FAULT
2984 SetLastError(STATUS_ACCESS_VIOLATION);
2986 __ENDTRY
2987 return ret;
2990 static BOOL CRYPT_AsnEncodeCertPolicyMapping(DWORD dwCertEncodingType,
2991 const CERT_POLICY_MAPPING *mapping, DWORD dwFlags, BYTE *pbEncoded,
2992 DWORD *pcbEncoded)
2994 struct AsnEncodeSequenceItem items[] = {
2995 { mapping->pszIssuerDomainPolicy, CRYPT_AsnEncodeOid, 0 },
2996 { mapping->pszSubjectDomainPolicy, CRYPT_AsnEncodeOid, 0 },
2999 if (!mapping->pszIssuerDomainPolicy || !mapping->pszSubjectDomainPolicy)
3001 SetLastError(E_INVALIDARG);
3002 return FALSE;
3004 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3005 sizeof(items) / sizeof(items[0]), dwFlags, NULL, pbEncoded, pcbEncoded);
3008 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyMappings(DWORD dwCertEncodingType,
3009 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3010 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3012 BOOL ret = FALSE;
3014 __TRY
3016 const CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3017 DWORD bytesNeeded = 0, lenBytes, size, i;
3019 ret = TRUE;
3020 for (i = 0; ret && i < info->cPolicyMapping; i++)
3022 ret = CRYPT_AsnEncodeCertPolicyMapping(dwCertEncodingType,
3023 &info->rgPolicyMapping[i], dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG,
3024 NULL, &size);
3025 if (ret)
3026 bytesNeeded += size;
3028 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3029 bytesNeeded += 1 + lenBytes;
3030 if (ret)
3032 if (!pbEncoded)
3033 *pcbEncoded = bytesNeeded;
3034 else
3036 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3037 pbEncoded, pcbEncoded, bytesNeeded)))
3039 BYTE *out;
3041 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3042 pbEncoded = *(BYTE **)pbEncoded;
3043 out = pbEncoded;
3044 *out++ = ASN_SEQUENCEOF;
3045 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3046 out += lenBytes;
3047 for (i = 0; ret && i < info->cPolicyMapping; i++)
3049 size = bytesNeeded;
3050 ret = CRYPT_AsnEncodeCertPolicyMapping(
3051 dwCertEncodingType, &info->rgPolicyMapping[i],
3052 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, out, &size);
3053 if (ret)
3055 out += size;
3056 bytesNeeded -= size;
3059 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3060 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3065 __EXCEPT_PAGE_FAULT
3067 SetLastError(STATUS_ACCESS_VIOLATION);
3069 __ENDTRY
3070 return ret;
3073 static BOOL WINAPI CRYPT_AsnEncodeCertPolicyConstraints(
3074 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
3075 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
3076 DWORD *pcbEncoded)
3078 BOOL ret = FALSE;
3080 __TRY
3082 const CERT_POLICY_CONSTRAINTS_INFO *info = pvStructInfo;
3083 struct AsnEncodeSequenceItem items[2];
3084 struct AsnEncodeTagSwappedItem swapped[2];
3085 DWORD cItem = 0, cSwapped = 0;
3087 if (info->fRequireExplicitPolicy)
3089 swapped[cSwapped].tag = ASN_CONTEXT | 0;
3090 swapped[cSwapped].pvStructInfo =
3091 &info->dwRequireExplicitPolicySkipCerts;
3092 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3093 items[cItem].pvStructInfo = &swapped[cSwapped];
3094 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3095 cSwapped++;
3096 cItem++;
3098 if (info->fInhibitPolicyMapping)
3100 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3101 swapped[cSwapped].pvStructInfo =
3102 &info->dwInhibitPolicyMappingSkipCerts;
3103 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
3104 items[cItem].pvStructInfo = &swapped[cSwapped];
3105 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3106 cSwapped++;
3107 cItem++;
3109 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3110 dwFlags, NULL, pbEncoded, pcbEncoded);
3112 __EXCEPT_PAGE_FAULT
3114 SetLastError(STATUS_ACCESS_VIOLATION);
3116 __ENDTRY
3117 return ret;
3120 static BOOL WINAPI CRYPT_AsnEncodeRsaPubKey(DWORD dwCertEncodingType,
3121 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3122 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3124 BOOL ret;
3126 __TRY
3128 const BLOBHEADER *hdr = pvStructInfo;
3130 if (hdr->bType != PUBLICKEYBLOB)
3132 SetLastError(E_INVALIDARG);
3133 ret = FALSE;
3135 else
3137 const RSAPUBKEY *rsaPubKey = (const RSAPUBKEY *)
3138 ((const BYTE *)pvStructInfo + sizeof(BLOBHEADER));
3139 CRYPT_INTEGER_BLOB blob = { rsaPubKey->bitlen / 8,
3140 (BYTE *)pvStructInfo + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) };
3141 struct AsnEncodeSequenceItem items[] = {
3142 { &blob, CRYPT_AsnEncodeUnsignedInteger, 0 },
3143 { &rsaPubKey->pubexp, CRYPT_AsnEncodeInt, 0 },
3146 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
3147 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
3148 pcbEncoded);
3151 __EXCEPT_PAGE_FAULT
3153 SetLastError(STATUS_ACCESS_VIOLATION);
3154 ret = FALSE;
3156 __ENDTRY
3157 return ret;
3160 BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
3161 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3162 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3164 BOOL ret;
3166 __TRY
3168 const CRYPT_DATA_BLOB *blob = pvStructInfo;
3169 DWORD bytesNeeded, lenBytes;
3171 TRACE("(%d, %p), %08x, %p, %p, %d\n", blob->cbData, blob->pbData,
3172 dwFlags, pEncodePara, pbEncoded, *pcbEncoded);
3174 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
3175 bytesNeeded = 1 + lenBytes + blob->cbData;
3176 if (!pbEncoded)
3178 *pcbEncoded = bytesNeeded;
3179 ret = TRUE;
3181 else
3183 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3184 pcbEncoded, bytesNeeded)))
3186 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3187 pbEncoded = *(BYTE **)pbEncoded;
3188 *pbEncoded++ = ASN_OCTETSTRING;
3189 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
3190 pbEncoded += lenBytes;
3191 if (blob->cbData)
3192 memcpy(pbEncoded, blob->pbData, blob->cbData);
3196 __EXCEPT_PAGE_FAULT
3198 SetLastError(STATUS_ACCESS_VIOLATION);
3199 ret = FALSE;
3201 __ENDTRY
3202 TRACE("returning %d (%08x)\n", ret, GetLastError());
3203 return ret;
3206 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
3207 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3208 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3210 BOOL ret;
3212 __TRY
3214 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3215 DWORD bytesNeeded, lenBytes, dataBytes;
3216 BYTE unusedBits;
3218 /* yep, MS allows cUnusedBits to be >= 8 */
3219 if (!blob->cUnusedBits)
3221 dataBytes = blob->cbData;
3222 unusedBits = 0;
3224 else if (blob->cbData * 8 > blob->cUnusedBits)
3226 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
3227 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
3228 blob->cUnusedBits;
3230 else
3232 dataBytes = 0;
3233 unusedBits = 0;
3235 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
3236 bytesNeeded = 1 + lenBytes + dataBytes + 1;
3237 if (!pbEncoded)
3239 *pcbEncoded = bytesNeeded;
3240 ret = TRUE;
3242 else
3244 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3245 pcbEncoded, bytesNeeded)))
3247 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3248 pbEncoded = *(BYTE **)pbEncoded;
3249 *pbEncoded++ = ASN_BITSTRING;
3250 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
3251 pbEncoded += lenBytes;
3252 *pbEncoded++ = unusedBits;
3253 if (dataBytes)
3255 BYTE mask = 0xff << unusedBits;
3257 if (dataBytes > 1)
3259 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
3260 pbEncoded += dataBytes - 1;
3262 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
3267 __EXCEPT_PAGE_FAULT
3269 SetLastError(STATUS_ACCESS_VIOLATION);
3270 ret = FALSE;
3272 __ENDTRY
3273 return ret;
3276 static BOOL WINAPI CRYPT_AsnEncodeBitsSwapBytes(DWORD dwCertEncodingType,
3277 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3278 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3280 BOOL ret;
3282 __TRY
3284 const CRYPT_BIT_BLOB *blob = pvStructInfo;
3285 CRYPT_BIT_BLOB newBlob = { blob->cbData, NULL, blob->cUnusedBits };
3287 ret = TRUE;
3288 if (newBlob.cbData)
3290 newBlob.pbData = CryptMemAlloc(newBlob.cbData);
3291 if (newBlob.pbData)
3293 DWORD i;
3295 for (i = 0; i < newBlob.cbData; i++)
3296 newBlob.pbData[newBlob.cbData - i - 1] = blob->pbData[i];
3298 else
3299 ret = FALSE;
3301 if (ret)
3302 ret = CRYPT_AsnEncodeBits(dwCertEncodingType, lpszStructType,
3303 &newBlob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3304 CryptMemFree(newBlob.pbData);
3306 __EXCEPT_PAGE_FAULT
3308 SetLastError(STATUS_ACCESS_VIOLATION);
3309 ret = FALSE;
3311 __ENDTRY
3312 return ret;
3315 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
3316 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3317 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3319 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
3321 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
3322 &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3325 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
3326 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3327 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3329 BOOL ret;
3331 __TRY
3333 DWORD significantBytes, lenBytes, bytesNeeded;
3334 BYTE padByte = 0;
3335 BOOL pad = FALSE;
3336 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3338 significantBytes = blob->cbData;
3339 if (significantBytes)
3341 if (blob->pbData[significantBytes - 1] & 0x80)
3343 /* negative, lop off leading (little-endian) 0xffs */
3344 for (; significantBytes > 0 &&
3345 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
3347 if (blob->pbData[significantBytes - 1] < 0x80)
3349 padByte = 0xff;
3350 pad = TRUE;
3353 else
3355 /* positive, lop off leading (little-endian) zeroes */
3356 for (; significantBytes > 0 &&
3357 !blob->pbData[significantBytes - 1]; significantBytes--)
3359 if (significantBytes == 0)
3360 significantBytes = 1;
3361 if (blob->pbData[significantBytes - 1] > 0x7f)
3363 padByte = 0;
3364 pad = TRUE;
3368 if (pad)
3369 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3370 else
3371 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3372 bytesNeeded = 1 + lenBytes + significantBytes;
3373 if (pad)
3374 bytesNeeded++;
3375 if (!pbEncoded)
3377 *pcbEncoded = bytesNeeded;
3378 ret = TRUE;
3380 else
3382 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3383 pcbEncoded, bytesNeeded)))
3385 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3386 pbEncoded = *(BYTE **)pbEncoded;
3387 *pbEncoded++ = ASN_INTEGER;
3388 if (pad)
3390 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3391 pbEncoded += lenBytes;
3392 *pbEncoded++ = padByte;
3394 else
3396 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3397 pbEncoded += lenBytes;
3399 for (; significantBytes > 0; significantBytes--)
3400 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3404 __EXCEPT_PAGE_FAULT
3406 SetLastError(STATUS_ACCESS_VIOLATION);
3407 ret = FALSE;
3409 __ENDTRY
3410 return ret;
3413 static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
3414 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3415 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3417 BOOL ret;
3419 __TRY
3421 DWORD significantBytes, lenBytes, bytesNeeded;
3422 BOOL pad = FALSE;
3423 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3425 significantBytes = blob->cbData;
3426 if (significantBytes)
3428 /* positive, lop off leading (little-endian) zeroes */
3429 for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
3430 significantBytes--)
3432 if (significantBytes == 0)
3433 significantBytes = 1;
3434 if (blob->pbData[significantBytes - 1] > 0x7f)
3435 pad = TRUE;
3437 if (pad)
3438 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
3439 else
3440 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
3441 bytesNeeded = 1 + lenBytes + significantBytes;
3442 if (pad)
3443 bytesNeeded++;
3444 if (!pbEncoded)
3446 *pcbEncoded = bytesNeeded;
3447 ret = TRUE;
3449 else
3451 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3452 pcbEncoded, bytesNeeded)))
3454 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3455 pbEncoded = *(BYTE **)pbEncoded;
3456 *pbEncoded++ = ASN_INTEGER;
3457 if (pad)
3459 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
3460 pbEncoded += lenBytes;
3461 *pbEncoded++ = 0;
3463 else
3465 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
3466 pbEncoded += lenBytes;
3468 for (; significantBytes > 0; significantBytes--)
3469 *(pbEncoded++) = blob->pbData[significantBytes - 1];
3473 __EXCEPT_PAGE_FAULT
3475 SetLastError(STATUS_ACCESS_VIOLATION);
3476 ret = FALSE;
3478 __ENDTRY
3479 return ret;
3482 static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
3483 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3484 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3486 CRYPT_INTEGER_BLOB blob;
3487 BOOL ret;
3489 /* Encode as an unsigned integer, then change the tag to enumerated */
3490 blob.cbData = sizeof(DWORD);
3491 blob.pbData = (BYTE *)pvStructInfo;
3492 ret = CRYPT_AsnEncodeUnsignedInteger(dwCertEncodingType,
3493 X509_MULTI_BYTE_UINT, &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3494 if (ret && pbEncoded)
3496 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3497 pbEncoded = *(BYTE **)pbEncoded;
3498 pbEncoded[0] = ASN_ENUMERATED;
3500 return ret;
3503 static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
3504 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3505 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3507 BOOL ret;
3509 __TRY
3511 SYSTEMTIME sysTime;
3512 /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
3513 * temporary buffer because the output buffer is not NULL-terminated.
3515 char buf[16];
3516 static const DWORD bytesNeeded = sizeof(buf) - 1;
3518 if (!pbEncoded)
3520 *pcbEncoded = bytesNeeded;
3521 ret = TRUE;
3523 else
3525 /* Sanity check the year, this is a two-digit year format */
3526 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3527 if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
3529 SetLastError(CRYPT_E_BAD_ENCODE);
3530 ret = FALSE;
3532 if (ret)
3534 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3535 pbEncoded, pcbEncoded, bytesNeeded)))
3537 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3538 pbEncoded = *(BYTE **)pbEncoded;
3539 buf[0] = ASN_UTCTIME;
3540 buf[1] = bytesNeeded - 2;
3541 snprintf(buf + 2, sizeof(buf) - 2,
3542 "%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
3543 sysTime.wYear - 2000 : sysTime.wYear - 1900,
3544 sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3545 sysTime.wMinute, sysTime.wSecond);
3546 memcpy(pbEncoded, buf, bytesNeeded);
3551 __EXCEPT_PAGE_FAULT
3553 SetLastError(STATUS_ACCESS_VIOLATION);
3554 ret = FALSE;
3556 __ENDTRY
3557 return ret;
3560 static BOOL CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
3561 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3562 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3564 BOOL ret;
3566 __TRY
3568 SYSTEMTIME sysTime;
3569 /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
3570 * temporary buffer because the output buffer is not NULL-terminated.
3572 char buf[18];
3573 static const DWORD bytesNeeded = sizeof(buf) - 1;
3575 if (!pbEncoded)
3577 *pcbEncoded = bytesNeeded;
3578 ret = TRUE;
3580 else
3582 ret = FileTimeToSystemTime(pvStructInfo, &sysTime);
3583 if (ret)
3584 ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3585 pcbEncoded, bytesNeeded);
3586 if (ret)
3588 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3589 pbEncoded = *(BYTE **)pbEncoded;
3590 buf[0] = ASN_GENERALTIME;
3591 buf[1] = bytesNeeded - 2;
3592 snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
3593 sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour,
3594 sysTime.wMinute, sysTime.wSecond);
3595 memcpy(pbEncoded, buf, bytesNeeded);
3599 __EXCEPT_PAGE_FAULT
3601 SetLastError(STATUS_ACCESS_VIOLATION);
3602 ret = FALSE;
3604 __ENDTRY
3605 return ret;
3608 static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
3609 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3610 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3612 BOOL ret;
3614 __TRY
3616 SYSTEMTIME sysTime;
3618 /* Check the year, if it's in the UTCTime range call that encode func */
3619 if (!FileTimeToSystemTime(pvStructInfo, &sysTime))
3620 return FALSE;
3621 if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
3622 ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
3623 pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3624 else
3625 ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
3626 lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
3627 pcbEncoded);
3629 __EXCEPT_PAGE_FAULT
3631 SetLastError(STATUS_ACCESS_VIOLATION);
3632 ret = FALSE;
3634 __ENDTRY
3635 return ret;
3638 static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
3639 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3640 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3642 BOOL ret;
3644 __TRY
3646 DWORD bytesNeeded, dataLen, lenBytes, i;
3647 const CRYPT_SEQUENCE_OF_ANY *seq = pvStructInfo;
3649 for (i = 0, dataLen = 0; i < seq->cValue; i++)
3650 dataLen += seq->rgValue[i].cbData;
3651 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3652 bytesNeeded = 1 + lenBytes + dataLen;
3653 if (!pbEncoded)
3655 *pcbEncoded = bytesNeeded;
3656 ret = TRUE;
3658 else
3660 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
3661 pcbEncoded, bytesNeeded)))
3663 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3664 pbEncoded = *(BYTE **)pbEncoded;
3665 *pbEncoded++ = ASN_SEQUENCEOF;
3666 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
3667 pbEncoded += lenBytes;
3668 for (i = 0; i < seq->cValue; i++)
3670 memcpy(pbEncoded, seq->rgValue[i].pbData,
3671 seq->rgValue[i].cbData);
3672 pbEncoded += seq->rgValue[i].cbData;
3677 __EXCEPT_PAGE_FAULT
3679 SetLastError(STATUS_ACCESS_VIOLATION);
3680 ret = FALSE;
3682 __ENDTRY
3683 return ret;
3686 static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
3687 BYTE *pbEncoded, DWORD *pcbEncoded)
3689 BOOL ret = TRUE;
3690 struct AsnEncodeSequenceItem items[3] = { { 0 } };
3691 struct AsnConstructedItem constructed = { 0 };
3692 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
3693 DWORD cItem = 0, cSwapped = 0;
3695 switch (distPoint->DistPointName.dwDistPointNameChoice)
3697 case CRL_DIST_POINT_NO_NAME:
3698 /* do nothing */
3699 break;
3700 case CRL_DIST_POINT_FULL_NAME:
3701 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3702 swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
3703 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3704 constructed.tag = 0;
3705 constructed.pvStructInfo = &swapped[cSwapped];
3706 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3707 items[cItem].pvStructInfo = &constructed;
3708 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3709 cSwapped++;
3710 cItem++;
3711 break;
3712 case CRL_DIST_POINT_ISSUER_RDN_NAME:
3713 FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
3714 ret = FALSE;
3715 break;
3716 default:
3717 ret = FALSE;
3719 if (ret && distPoint->ReasonFlags.cbData)
3721 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3722 swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
3723 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3724 items[cItem].pvStructInfo = &swapped[cSwapped];
3725 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3726 cSwapped++;
3727 cItem++;
3729 if (ret && distPoint->CRLIssuer.cAltEntry)
3731 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
3732 swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
3733 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3734 items[cItem].pvStructInfo = &swapped[cSwapped];
3735 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3736 cSwapped++;
3737 cItem++;
3739 if (ret)
3740 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
3741 pbEncoded, pcbEncoded);
3742 return ret;
3745 static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
3746 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3747 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3749 BOOL ret;
3751 __TRY
3753 const CRL_DIST_POINTS_INFO *info = pvStructInfo;
3755 if (!info->cDistPoint)
3757 SetLastError(E_INVALIDARG);
3758 ret = FALSE;
3760 else
3762 DWORD bytesNeeded, dataLen, lenBytes, i;
3764 ret = TRUE;
3765 for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
3767 DWORD len;
3769 ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
3770 &len);
3771 if (ret)
3772 dataLen += len;
3773 else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
3775 /* Have to propagate index of failing character */
3776 *pcbEncoded = len;
3779 if (ret)
3781 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
3782 bytesNeeded = 1 + lenBytes + dataLen;
3783 if (!pbEncoded)
3785 *pcbEncoded = bytesNeeded;
3786 ret = TRUE;
3788 else
3790 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3791 pbEncoded, pcbEncoded, bytesNeeded)))
3793 BYTE *out;
3795 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3796 pbEncoded = *(BYTE **)pbEncoded;
3797 out = pbEncoded;
3798 *out++ = ASN_SEQUENCEOF;
3799 CRYPT_EncodeLen(dataLen, out, &lenBytes);
3800 out += lenBytes;
3801 for (i = 0; ret && i < info->cDistPoint; i++)
3803 DWORD len = dataLen;
3805 ret = CRYPT_AsnEncodeDistPoint(
3806 &info->rgDistPoint[i], out, &len);
3807 if (ret)
3809 out += len;
3810 dataLen -= len;
3813 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3814 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3820 __EXCEPT_PAGE_FAULT
3822 SetLastError(STATUS_ACCESS_VIOLATION);
3823 ret = FALSE;
3825 __ENDTRY
3826 return ret;
3829 static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3830 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3831 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3833 BOOL ret;
3835 __TRY
3837 const CERT_ENHKEY_USAGE *usage = pvStructInfo;
3838 DWORD bytesNeeded = 0, lenBytes, size, i;
3840 ret = TRUE;
3841 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3843 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3844 usage->rgpszUsageIdentifier[i],
3845 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
3846 if (ret)
3847 bytesNeeded += size;
3849 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
3850 bytesNeeded += 1 + lenBytes;
3851 if (ret)
3853 if (!pbEncoded)
3854 *pcbEncoded = bytesNeeded;
3855 else
3857 if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
3858 pbEncoded, pcbEncoded, bytesNeeded)))
3860 BYTE *out;
3862 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
3863 pbEncoded = *(BYTE **)pbEncoded;
3864 out = pbEncoded;
3865 *out++ = ASN_SEQUENCEOF;
3866 CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, out, &lenBytes);
3867 out += lenBytes;
3868 for (i = 0; ret && i < usage->cUsageIdentifier; i++)
3870 size = bytesNeeded;
3871 ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
3872 usage->rgpszUsageIdentifier[i],
3873 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, out, &size);
3874 if (ret)
3876 out += size;
3877 bytesNeeded -= size;
3880 if (!ret && (dwFlags & CRYPT_ENCODE_ALLOC_FLAG))
3881 CRYPT_FreeSpace(pEncodePara, pbEncoded);
3886 __EXCEPT_PAGE_FAULT
3888 SetLastError(STATUS_ACCESS_VIOLATION);
3889 ret = FALSE;
3891 __ENDTRY
3892 return ret;
3895 static BOOL WINAPI CRYPT_AsnEncodeIssuingDistPoint(DWORD dwCertEncodingType,
3896 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3897 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3899 BOOL ret;
3901 __TRY
3903 const CRL_ISSUING_DIST_POINT *point = pvStructInfo;
3904 struct AsnEncodeSequenceItem items[6] = { { 0 } };
3905 struct AsnConstructedItem constructed = { 0 };
3906 struct AsnEncodeTagSwappedItem swapped[5] = { { 0 } };
3907 DWORD cItem = 0, cSwapped = 0;
3909 ret = TRUE;
3910 switch (point->DistPointName.dwDistPointNameChoice)
3912 case CRL_DIST_POINT_NO_NAME:
3913 /* do nothing */
3914 break;
3915 case CRL_DIST_POINT_FULL_NAME:
3916 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
3917 swapped[cSwapped].pvStructInfo = &point->DistPointName.u.FullName;
3918 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
3919 constructed.tag = 0;
3920 constructed.pvStructInfo = &swapped[cSwapped];
3921 constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
3922 items[cItem].pvStructInfo = &constructed;
3923 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
3924 cSwapped++;
3925 cItem++;
3926 break;
3927 default:
3928 SetLastError(E_INVALIDARG);
3929 ret = FALSE;
3931 if (ret && point->fOnlyContainsUserCerts)
3933 swapped[cSwapped].tag = ASN_CONTEXT | 1;
3934 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsUserCerts;
3935 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3936 items[cItem].pvStructInfo = &swapped[cSwapped];
3937 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3938 cSwapped++;
3939 cItem++;
3941 if (ret && point->fOnlyContainsCACerts)
3943 swapped[cSwapped].tag = ASN_CONTEXT | 2;
3944 swapped[cSwapped].pvStructInfo = &point->fOnlyContainsCACerts;
3945 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3946 items[cItem].pvStructInfo = &swapped[cSwapped];
3947 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3948 cSwapped++;
3949 cItem++;
3951 if (ret && point->OnlySomeReasonFlags.cbData)
3953 swapped[cSwapped].tag = ASN_CONTEXT | 3;
3954 swapped[cSwapped].pvStructInfo = &point->OnlySomeReasonFlags;
3955 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
3956 items[cItem].pvStructInfo = &swapped[cSwapped];
3957 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3958 cSwapped++;
3959 cItem++;
3961 if (ret && point->fIndirectCRL)
3963 swapped[cSwapped].tag = ASN_CONTEXT | 4;
3964 swapped[cSwapped].pvStructInfo = &point->fIndirectCRL;
3965 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBool;
3966 items[cItem].pvStructInfo = &swapped[cSwapped];
3967 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
3968 cSwapped++;
3969 cItem++;
3971 if (ret)
3972 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
3973 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
3975 __EXCEPT_PAGE_FAULT
3977 SetLastError(STATUS_ACCESS_VIOLATION);
3978 ret = FALSE;
3980 __ENDTRY
3981 return ret;
3984 static BOOL CRYPT_AsnEncodeGeneralSubtree(DWORD dwCertEncodingType,
3985 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
3986 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
3988 BOOL ret;
3989 const CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
3990 struct AsnEncodeSequenceItem items[3] = {
3991 { &subtree->Base, CRYPT_AsnEncodeAltNameEntry, 0 },
3992 { 0 }
3994 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
3995 DWORD cItem = 1, cSwapped = 0;
3997 if (subtree->dwMinimum)
3999 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4000 swapped[cSwapped].pvStructInfo = &subtree->dwMinimum;
4001 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4002 items[cItem].pvStructInfo = &swapped[cSwapped];
4003 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4004 cSwapped++;
4005 cItem++;
4007 if (subtree->fMaximum)
4009 swapped[cSwapped].tag = ASN_CONTEXT | 1;
4010 swapped[cSwapped].pvStructInfo = &subtree->dwMaximum;
4011 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInt;
4012 items[cItem].pvStructInfo = &swapped[cSwapped];
4013 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4014 cSwapped++;
4015 cItem++;
4017 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem, dwFlags,
4018 pEncodePara, pbEncoded, pcbEncoded);
4019 return ret;
4022 static BOOL WINAPI CRYPT_AsnEncodeNameConstraints(DWORD dwCertEncodingType,
4023 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4024 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4026 BOOL ret = FALSE;
4027 CRYPT_BLOB_ARRAY permitted = { 0, NULL }, excluded = { 0, NULL };
4029 TRACE("%p\n", pvStructInfo);
4031 __TRY
4033 const CERT_NAME_CONSTRAINTS_INFO *constraints = pvStructInfo;
4034 struct AsnEncodeSequenceItem items[2] = { { 0 } };
4035 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4036 DWORD i, cItem = 0, cSwapped = 0;
4038 ret = TRUE;
4039 if (constraints->cPermittedSubtree)
4041 permitted.rgBlob = CryptMemAlloc(
4042 constraints->cPermittedSubtree * sizeof(CRYPT_DER_BLOB));
4043 if (permitted.rgBlob)
4045 permitted.cBlob = constraints->cPermittedSubtree;
4046 memset(permitted.rgBlob, 0,
4047 permitted.cBlob * sizeof(CRYPT_DER_BLOB));
4048 for (i = 0; ret && i < permitted.cBlob; i++)
4049 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4050 NULL, &constraints->rgPermittedSubtree[i],
4051 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4052 (BYTE *)&permitted.rgBlob[i].pbData,
4053 &permitted.rgBlob[i].cbData);
4054 if (ret)
4056 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4057 swapped[cSwapped].pvStructInfo = &permitted;
4058 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4059 items[cItem].pvStructInfo = &swapped[cSwapped];
4060 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4061 cSwapped++;
4062 cItem++;
4065 else
4066 ret = FALSE;
4068 if (constraints->cExcludedSubtree)
4070 excluded.rgBlob = CryptMemAlloc(
4071 constraints->cExcludedSubtree * sizeof(CRYPT_DER_BLOB));
4072 if (excluded.rgBlob)
4074 excluded.cBlob = constraints->cExcludedSubtree;
4075 memset(excluded.rgBlob, 0,
4076 excluded.cBlob * sizeof(CRYPT_DER_BLOB));
4077 for (i = 0; ret && i < excluded.cBlob; i++)
4078 ret = CRYPT_AsnEncodeGeneralSubtree(dwCertEncodingType,
4079 NULL, &constraints->rgExcludedSubtree[i],
4080 CRYPT_ENCODE_ALLOC_FLAG, NULL,
4081 (BYTE *)&excluded.rgBlob[i].pbData,
4082 &excluded.rgBlob[i].cbData);
4083 if (ret)
4085 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4086 swapped[cSwapped].pvStructInfo = &excluded;
4087 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeSet;
4088 items[cItem].pvStructInfo = &swapped[cSwapped];
4089 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4090 cSwapped++;
4091 cItem++;
4094 else
4095 ret = FALSE;
4097 if (ret)
4098 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4099 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4100 for (i = 0; i < permitted.cBlob; i++)
4101 LocalFree(permitted.rgBlob[i].pbData);
4102 for (i = 0; i < excluded.cBlob; i++)
4103 LocalFree(excluded.rgBlob[i].pbData);
4105 __EXCEPT_PAGE_FAULT
4107 SetLastError(STATUS_ACCESS_VIOLATION);
4109 __ENDTRY
4110 CryptMemFree(permitted.rgBlob);
4111 CryptMemFree(excluded.rgBlob);
4112 TRACE("returning %d\n", ret);
4113 return ret;
4116 static BOOL WINAPI CRYPT_AsnEncodeIssuerSerialNumber(
4117 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
4118 DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
4119 DWORD *pcbEncoded)
4121 BOOL ret;
4122 const CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4123 struct AsnEncodeSequenceItem items[] = {
4124 { &issuerSerial->Issuer, CRYPT_CopyEncodedBlob, 0 },
4125 { &issuerSerial->SerialNumber, CRYPT_AsnEncodeInteger, 0 },
4128 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4129 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4130 pcbEncoded);
4131 return ret;
4134 static BOOL WINAPI CRYPT_AsnEncodePKCSSignerInfo(DWORD dwCertEncodingType,
4135 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4136 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4138 BOOL ret = FALSE;
4140 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4142 SetLastError(E_INVALIDARG);
4143 return FALSE;
4146 __TRY
4148 const CMSG_SIGNER_INFO *info = pvStructInfo;
4150 if (!info->Issuer.cbData)
4151 SetLastError(E_INVALIDARG);
4152 else
4154 struct AsnEncodeSequenceItem items[7] = {
4155 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4156 { &info->Issuer, CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4157 { &info->HashAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams,
4158 0 },
4160 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4161 DWORD cItem = 3, cSwapped = 0;
4163 if (info->AuthAttrs.cAttr)
4165 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4166 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4167 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4168 items[cItem].pvStructInfo = &swapped[cSwapped];
4169 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4170 cSwapped++;
4171 cItem++;
4173 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4174 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4175 cItem++;
4176 items[cItem].pvStructInfo = &info->EncryptedHash;
4177 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4178 cItem++;
4179 if (info->UnauthAttrs.cAttr)
4181 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4182 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4183 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4184 items[cItem].pvStructInfo = &swapped[cSwapped];
4185 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4186 cSwapped++;
4187 cItem++;
4189 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4190 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4193 __EXCEPT_PAGE_FAULT
4195 SetLastError(STATUS_ACCESS_VIOLATION);
4197 __ENDTRY
4198 return ret;
4201 static BOOL WINAPI CRYPT_AsnEncodeCMSSignerInfo(DWORD dwCertEncodingType,
4202 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4203 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4205 BOOL ret = FALSE;
4207 if (!(dwCertEncodingType & PKCS_7_ASN_ENCODING))
4209 SetLastError(E_INVALIDARG);
4210 return FALSE;
4213 __TRY
4215 const CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
4217 if (info->SignerId.dwIdChoice != CERT_ID_ISSUER_SERIAL_NUMBER &&
4218 info->SignerId.dwIdChoice != CERT_ID_KEY_IDENTIFIER)
4219 SetLastError(E_INVALIDARG);
4220 else if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER &&
4221 !info->SignerId.u.IssuerSerialNumber.Issuer.cbData)
4222 SetLastError(E_INVALIDARG);
4223 else
4225 struct AsnEncodeSequenceItem items[7] = {
4226 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4228 struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
4229 DWORD cItem = 1, cSwapped = 0;
4231 if (info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER)
4233 items[cItem].pvStructInfo =
4234 &info->SignerId.u.IssuerSerialNumber.Issuer;
4235 items[cItem].encodeFunc =
4236 CRYPT_AsnEncodeIssuerSerialNumber;
4237 cItem++;
4239 else
4241 swapped[cSwapped].tag = ASN_CONTEXT | 0;
4242 swapped[cSwapped].pvStructInfo = &info->SignerId.u.KeyId;
4243 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeOctets;
4244 items[cItem].pvStructInfo = &swapped[cSwapped];
4245 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4246 cSwapped++;
4247 cItem++;
4249 items[cItem].pvStructInfo = &info->HashAlgorithm;
4250 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4251 cItem++;
4252 if (info->AuthAttrs.cAttr)
4254 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
4255 swapped[cSwapped].pvStructInfo = &info->AuthAttrs;
4256 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4257 items[cItem].pvStructInfo = &swapped[cSwapped];
4258 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4259 cSwapped++;
4260 cItem++;
4262 items[cItem].pvStructInfo = &info->HashEncryptionAlgorithm;
4263 items[cItem].encodeFunc = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4264 cItem++;
4265 items[cItem].pvStructInfo = &info->EncryptedHash;
4266 items[cItem].encodeFunc = CRYPT_AsnEncodeOctets;
4267 cItem++;
4268 if (info->UnauthAttrs.cAttr)
4270 swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
4271 swapped[cSwapped].pvStructInfo = &info->UnauthAttrs;
4272 swapped[cSwapped].encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4273 items[cItem].pvStructInfo = &swapped[cSwapped];
4274 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4275 cSwapped++;
4276 cItem++;
4278 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
4279 dwFlags, pEncodePara, pbEncoded, pcbEncoded);
4282 __EXCEPT_PAGE_FAULT
4284 SetLastError(STATUS_ACCESS_VIOLATION);
4286 __ENDTRY
4287 return ret;
4290 BOOL CRYPT_AsnEncodeCMSSignedInfo(CRYPT_SIGNED_INFO *signedInfo, void *pvData,
4291 DWORD *pcbData)
4293 struct AsnEncodeSequenceItem items[7] = {
4294 { &signedInfo->version, CRYPT_AsnEncodeInt, 0 },
4296 struct DERSetDescriptor digestAlgorithmsSet = { 0 }, certSet = { 0 };
4297 struct DERSetDescriptor crlSet = { 0 }, signerSet = { 0 };
4298 struct AsnEncodeTagSwappedItem swapped[2] = { { 0 } };
4299 DWORD cItem = 1, cSwapped = 0;
4300 BOOL ret = TRUE;
4302 if (signedInfo->cSignerInfo)
4304 digestAlgorithmsSet.cItems = signedInfo->cSignerInfo;
4305 digestAlgorithmsSet.items = signedInfo->rgSignerInfo;
4306 digestAlgorithmsSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4307 digestAlgorithmsSet.itemOffset =
4308 offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm);
4309 digestAlgorithmsSet.encode = CRYPT_AsnEncodeAlgorithmIdWithNullParams;
4310 items[cItem].pvStructInfo = &digestAlgorithmsSet;
4311 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4312 cItem++;
4314 items[cItem].pvStructInfo = &signedInfo->content;
4315 items[cItem].encodeFunc = CRYPT_AsnEncodePKCSContentInfoInternal;
4316 cItem++;
4317 if (signedInfo->cCertEncoded)
4319 certSet.cItems = signedInfo->cCertEncoded;
4320 certSet.items = signedInfo->rgCertEncoded;
4321 certSet.itemSize = sizeof(CERT_BLOB);
4322 certSet.itemOffset = 0;
4323 certSet.encode = CRYPT_CopyEncodedBlob;
4324 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 0;
4325 swapped[cSwapped].pvStructInfo = &certSet;
4326 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4327 items[cItem].pvStructInfo = &swapped[cSwapped];
4328 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4329 cSwapped++;
4330 cItem++;
4332 if (signedInfo->cCrlEncoded)
4334 crlSet.cItems = signedInfo->cCrlEncoded;
4335 crlSet.items = signedInfo->rgCrlEncoded;
4336 crlSet.itemSize = sizeof(CRL_BLOB);
4337 crlSet.itemOffset = 0;
4338 crlSet.encode = CRYPT_CopyEncodedBlob;
4339 swapped[cSwapped].tag = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
4340 swapped[cSwapped].pvStructInfo = &crlSet;
4341 swapped[cSwapped].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4342 items[cItem].pvStructInfo = &swapped[cSwapped];
4343 items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
4344 cSwapped++;
4345 cItem++;
4347 if (ret && signedInfo->cSignerInfo)
4349 signerSet.cItems = signedInfo->cSignerInfo;
4350 signerSet.items = signedInfo->rgSignerInfo;
4351 signerSet.itemSize = sizeof(CMSG_CMS_SIGNER_INFO);
4352 signerSet.itemOffset = 0;
4353 signerSet.encode = CRYPT_AsnEncodeCMSSignerInfo;
4354 items[cItem].pvStructInfo = &signerSet;
4355 items[cItem].encodeFunc = CRYPT_DEREncodeItemsAsSet;
4356 cItem++;
4358 if (ret)
4359 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
4360 items, cItem, 0, NULL, pvData, pcbData);
4362 return ret;
4365 static BOOL WINAPI CRYPT_AsnEncodeRecipientInfo(DWORD dwCertEncodingType,
4366 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4367 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4369 const CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
4370 struct AsnEncodeSequenceItem items[] = {
4371 { &info->dwVersion, CRYPT_AsnEncodeInt, 0 },
4372 { &info->RecipientId.u.IssuerSerialNumber,
4373 CRYPT_AsnEncodeIssuerSerialNumber, 0 },
4374 { &info->KeyEncryptionAlgorithm,
4375 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4376 { &info->EncryptedKey, CRYPT_AsnEncodeOctets, 0 },
4379 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4380 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4381 pcbEncoded);
4384 static BOOL WINAPI CRYPT_AsnEncodeEncryptedContentInfo(DWORD dwCertEncodingType,
4385 LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
4386 PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
4388 const CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
4389 struct AsnEncodeTagSwappedItem swapped = { ASN_CONTEXT | 0,
4390 &info->encryptedContent, CRYPT_AsnEncodeOctets };
4391 struct AsnEncodeSequenceItem items[] = {
4392 { info->contentType, CRYPT_AsnEncodeOid, 0 },
4393 { &info->contentEncryptionAlgorithm,
4394 CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
4395 { &swapped, CRYPT_AsnEncodeSwapTag, 0 },
4398 return CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
4399 sizeof(items) / sizeof(items[0]), dwFlags, pEncodePara, pbEncoded,
4400 pcbEncoded);
4403 BOOL CRYPT_AsnEncodePKCSEnvelopedData(const CRYPT_ENVELOPED_DATA *envelopedData,
4404 void *pvData, DWORD *pcbData)
4406 struct DERSetDescriptor recipientInfosSet = { envelopedData->cRecipientInfo,
4407 envelopedData->rgRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), 0,
4408 CRYPT_AsnEncodeRecipientInfo };
4409 struct AsnEncodeSequenceItem items[] = {
4410 { &envelopedData->version, CRYPT_AsnEncodeInt, 0 },
4411 { &recipientInfosSet, CRYPT_DEREncodeItemsAsSet, 0 },
4412 { &envelopedData->encryptedContentInfo,
4413 CRYPT_AsnEncodeEncryptedContentInfo, 0 },
4416 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items,
4417 sizeof(items) / sizeof(items[0]), 0, NULL, pvData, pcbData);
4420 static CryptEncodeObjectExFunc CRYPT_GetBuiltinEncoder(DWORD dwCertEncodingType,
4421 LPCSTR lpszStructType)
4423 CryptEncodeObjectExFunc encodeFunc = NULL;
4425 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4426 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4428 SetLastError(ERROR_FILE_NOT_FOUND);
4429 return NULL;
4432 if (IS_INTOID(lpszStructType))
4434 switch (LOWORD(lpszStructType))
4436 case LOWORD(X509_CERT):
4437 encodeFunc = CRYPT_AsnEncodeCert;
4438 break;
4439 case LOWORD(X509_CERT_TO_BE_SIGNED):
4440 encodeFunc = CRYPT_AsnEncodeCertInfo;
4441 break;
4442 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4443 encodeFunc = CRYPT_AsnEncodeCRLInfo;
4444 break;
4445 case LOWORD(X509_EXTENSIONS):
4446 encodeFunc = CRYPT_AsnEncodeExtensions;
4447 break;
4448 case LOWORD(X509_NAME_VALUE):
4449 encodeFunc = CRYPT_AsnEncodeNameValue;
4450 break;
4451 case LOWORD(X509_NAME):
4452 encodeFunc = CRYPT_AsnEncodeName;
4453 break;
4454 case LOWORD(X509_PUBLIC_KEY_INFO):
4455 encodeFunc = CRYPT_AsnEncodePubKeyInfo;
4456 break;
4457 case LOWORD(X509_AUTHORITY_KEY_ID):
4458 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4459 break;
4460 case LOWORD(X509_ALTERNATE_NAME):
4461 encodeFunc = CRYPT_AsnEncodeAltName;
4462 break;
4463 case LOWORD(X509_BASIC_CONSTRAINTS):
4464 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4465 break;
4466 case LOWORD(X509_BASIC_CONSTRAINTS2):
4467 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4468 break;
4469 case LOWORD(X509_CERT_POLICIES):
4470 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4471 break;
4472 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4473 encodeFunc = CRYPT_AsnEncodeRsaPubKey;
4474 break;
4475 case LOWORD(X509_UNICODE_NAME):
4476 encodeFunc = CRYPT_AsnEncodeUnicodeName;
4477 break;
4478 case LOWORD(PKCS_CONTENT_INFO):
4479 encodeFunc = CRYPT_AsnEncodePKCSContentInfo;
4480 break;
4481 case LOWORD(PKCS_ATTRIBUTE):
4482 encodeFunc = CRYPT_AsnEncodePKCSAttribute;
4483 break;
4484 case LOWORD(X509_UNICODE_NAME_VALUE):
4485 encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
4486 break;
4487 case LOWORD(X509_OCTET_STRING):
4488 encodeFunc = CRYPT_AsnEncodeOctets;
4489 break;
4490 case LOWORD(X509_BITS):
4491 case LOWORD(X509_KEY_USAGE):
4492 encodeFunc = CRYPT_AsnEncodeBits;
4493 break;
4494 case LOWORD(X509_INTEGER):
4495 encodeFunc = CRYPT_AsnEncodeInt;
4496 break;
4497 case LOWORD(X509_MULTI_BYTE_INTEGER):
4498 encodeFunc = CRYPT_AsnEncodeInteger;
4499 break;
4500 case LOWORD(X509_MULTI_BYTE_UINT):
4501 encodeFunc = CRYPT_AsnEncodeUnsignedInteger;
4502 break;
4503 case LOWORD(X509_ENUMERATED):
4504 encodeFunc = CRYPT_AsnEncodeEnumerated;
4505 break;
4506 case LOWORD(X509_CHOICE_OF_TIME):
4507 encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
4508 break;
4509 case LOWORD(X509_AUTHORITY_KEY_ID2):
4510 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4511 break;
4512 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4513 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4514 break;
4515 case LOWORD(X509_SEQUENCE_OF_ANY):
4516 encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
4517 break;
4518 case LOWORD(PKCS_UTC_TIME):
4519 encodeFunc = CRYPT_AsnEncodeUtcTime;
4520 break;
4521 case LOWORD(X509_CRL_DIST_POINTS):
4522 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4523 break;
4524 case LOWORD(X509_ENHANCED_KEY_USAGE):
4525 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4526 break;
4527 case LOWORD(PKCS_CTL):
4528 encodeFunc = CRYPT_AsnEncodeCTL;
4529 break;
4530 case LOWORD(PKCS_SMIME_CAPABILITIES):
4531 encodeFunc = CRYPT_AsnEncodeSMIMECapabilities;
4532 break;
4533 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
4534 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4535 break;
4536 case LOWORD(PKCS_ATTRIBUTES):
4537 encodeFunc = CRYPT_AsnEncodePKCSAttributes;
4538 break;
4539 case LOWORD(X509_ISSUING_DIST_POINT):
4540 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4541 break;
4542 case LOWORD(X509_NAME_CONSTRAINTS):
4543 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4544 break;
4545 case LOWORD(X509_POLICY_MAPPINGS):
4546 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4547 break;
4548 case LOWORD(X509_POLICY_CONSTRAINTS):
4549 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4550 break;
4551 case LOWORD(PKCS7_SIGNER_INFO):
4552 encodeFunc = CRYPT_AsnEncodePKCSSignerInfo;
4553 break;
4554 case LOWORD(CMS_SIGNER_INFO):
4555 encodeFunc = CRYPT_AsnEncodeCMSSignerInfo;
4556 break;
4559 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4560 encodeFunc = CRYPT_AsnEncodeExtensions;
4561 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4562 encodeFunc = CRYPT_AsnEncodeUtcTime;
4563 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4564 encodeFunc = CRYPT_AsnEncodeUtcTime;
4565 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4566 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
4567 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
4568 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4569 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4570 encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
4571 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4572 encodeFunc = CRYPT_AsnEncodeEnumerated;
4573 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4574 encodeFunc = CRYPT_AsnEncodeBits;
4575 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4576 encodeFunc = CRYPT_AsnEncodeOctets;
4577 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4578 encodeFunc = CRYPT_AsnEncodeBasicConstraints;
4579 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4580 encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
4581 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4582 encodeFunc = CRYPT_AsnEncodeAltName;
4583 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4584 encodeFunc = CRYPT_AsnEncodeAltName;
4585 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4586 encodeFunc = CRYPT_AsnEncodeAltName;
4587 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4588 encodeFunc = CRYPT_AsnEncodeAltName;
4589 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4590 encodeFunc = CRYPT_AsnEncodeAltName;
4591 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4592 encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
4593 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
4594 encodeFunc = CRYPT_AsnEncodeCertPolicies;
4595 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
4596 encodeFunc = CRYPT_AsnEncodeCertPolicyMappings;
4597 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
4598 encodeFunc = CRYPT_AsnEncodeCertPolicyConstraints;
4599 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4600 encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
4601 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4602 encodeFunc = CRYPT_AsnEncodeIssuingDistPoint;
4603 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4604 encodeFunc = CRYPT_AsnEncodeNameConstraints;
4605 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4606 encodeFunc = CRYPT_AsnEncodeAuthorityInfoAccess;
4607 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
4608 encodeFunc = CRYPT_AsnEncodePolicyQualifierUserNotice;
4609 else if (!strcmp(lpszStructType, szOID_CTL))
4610 encodeFunc = CRYPT_AsnEncodeCTL;
4611 return encodeFunc;
4614 static CryptEncodeObjectFunc CRYPT_LoadEncoderFunc(DWORD dwCertEncodingType,
4615 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4617 static HCRYPTOIDFUNCSET set = NULL;
4618 CryptEncodeObjectFunc encodeFunc = NULL;
4620 if (!set)
4621 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_FUNC, 0);
4622 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4623 (void **)&encodeFunc, hFunc);
4624 return encodeFunc;
4627 static CryptEncodeObjectExFunc CRYPT_LoadEncoderExFunc(DWORD dwCertEncodingType,
4628 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4630 static HCRYPTOIDFUNCSET set = NULL;
4631 CryptEncodeObjectExFunc encodeFunc = NULL;
4633 if (!set)
4634 set = CryptInitOIDFunctionSet(CRYPT_OID_ENCODE_OBJECT_EX_FUNC, 0);
4635 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4636 (void **)&encodeFunc, hFunc);
4637 return encodeFunc;
4640 BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4641 const void *pvStructInfo, BYTE *pbEncoded, DWORD *pcbEncoded)
4643 BOOL ret = FALSE;
4644 HCRYPTOIDFUNCADDR hFunc = NULL;
4645 CryptEncodeObjectFunc pCryptEncodeObject = NULL;
4646 CryptEncodeObjectExFunc pCryptEncodeObjectEx = NULL;
4648 TRACE_(crypt)("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
4649 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
4650 pcbEncoded);
4652 if (!pbEncoded && !pcbEncoded)
4654 SetLastError(ERROR_INVALID_PARAMETER);
4655 return FALSE;
4658 if (!(pCryptEncodeObjectEx = CRYPT_GetBuiltinEncoder(dwCertEncodingType,
4659 lpszStructType)))
4661 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4662 debugstr_a(lpszStructType));
4663 pCryptEncodeObject = CRYPT_LoadEncoderFunc(dwCertEncodingType,
4664 lpszStructType, &hFunc);
4665 if (!pCryptEncodeObject)
4666 pCryptEncodeObjectEx = CRYPT_LoadEncoderExFunc(dwCertEncodingType,
4667 lpszStructType, &hFunc);
4669 if (pCryptEncodeObject)
4670 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4671 pvStructInfo, pbEncoded, pcbEncoded);
4672 else if (pCryptEncodeObjectEx)
4673 ret = pCryptEncodeObjectEx(dwCertEncodingType, lpszStructType,
4674 pvStructInfo, 0, NULL, pbEncoded, pcbEncoded);
4675 if (hFunc)
4676 CryptFreeOIDFunctionAddress(hFunc, 0);
4677 TRACE_(crypt)("returning %d\n", ret);
4678 return ret;
4681 BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4682 const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
4683 void *pvEncoded, DWORD *pcbEncoded)
4685 BOOL ret = FALSE;
4686 HCRYPTOIDFUNCADDR hFunc = NULL;
4687 CryptEncodeObjectExFunc encodeFunc = NULL;
4689 TRACE_(crypt)("(0x%08x, %s, %p, 0x%08x, %p, %p, %p)\n", dwCertEncodingType,
4690 debugstr_a(lpszStructType), pvStructInfo, dwFlags, pEncodePara,
4691 pvEncoded, pcbEncoded);
4693 if (!pvEncoded && !pcbEncoded)
4695 SetLastError(ERROR_INVALID_PARAMETER);
4696 return FALSE;
4699 SetLastError(NOERROR);
4700 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
4701 if (!pvEncoded) {
4702 SetLastError(ERROR_INVALID_PARAMETER);
4703 return FALSE;
4705 *(BYTE **)pvEncoded = NULL;
4707 encodeFunc = CRYPT_GetBuiltinEncoder(dwCertEncodingType, lpszStructType);
4708 if (!encodeFunc)
4710 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4711 debugstr_a(lpszStructType));
4712 encodeFunc = CRYPT_LoadEncoderExFunc(dwCertEncodingType, lpszStructType,
4713 &hFunc);
4715 if (encodeFunc)
4716 ret = encodeFunc(dwCertEncodingType, lpszStructType, pvStructInfo,
4717 dwFlags, pEncodePara, pvEncoded, pcbEncoded);
4718 else
4720 CryptEncodeObjectFunc pCryptEncodeObject =
4721 CRYPT_LoadEncoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4723 if (pCryptEncodeObject)
4725 if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
4727 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4728 pvStructInfo, NULL, pcbEncoded);
4729 if (ret && (ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
4730 pvEncoded, pcbEncoded, *pcbEncoded)))
4731 ret = pCryptEncodeObject(dwCertEncodingType,
4732 lpszStructType, pvStructInfo, *(BYTE **)pvEncoded,
4733 pcbEncoded);
4735 else
4736 ret = pCryptEncodeObject(dwCertEncodingType, lpszStructType,
4737 pvStructInfo, pvEncoded, pcbEncoded);
4740 if (hFunc)
4741 CryptFreeOIDFunctionAddress(hFunc, 0);
4742 TRACE_(crypt)("returning %d\n", ret);
4743 return ret;
4746 BOOL WINAPI PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4747 LPCWSTR szPassword, DWORD dwFlags)
4749 return PFXExportCertStoreEx(hStore, pPFX, szPassword, NULL, dwFlags);
4752 BOOL WINAPI PFXExportCertStoreEx(HCERTSTORE hStore, CRYPT_DATA_BLOB *pPFX,
4753 LPCWSTR szPassword, void *pvReserved, DWORD dwFlags)
4755 FIXME_(crypt)("(%p, %p, %p, %p, %08x): stub\n", hStore, pPFX, szPassword,
4756 pvReserved, dwFlags);
4757 return FALSE;
4760 BOOL WINAPI CryptExportPublicKeyInfo(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4761 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4763 return CryptExportPublicKeyInfoEx(hCryptProv, dwKeySpec, dwCertEncodingType,
4764 NULL, 0, NULL, pInfo, pcbInfo);
4767 static BOOL WINAPI CRYPT_ExportRsaPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4768 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4769 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4771 BOOL ret;
4772 HCRYPTKEY key;
4773 static CHAR oid[] = szOID_RSA_RSA;
4775 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4776 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4777 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4779 if (!pszPublicKeyObjId)
4780 pszPublicKeyObjId = oid;
4781 if ((ret = CryptGetUserKey(hCryptProv, dwKeySpec, &key)))
4783 DWORD keySize = 0;
4785 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &keySize);
4786 if (ret)
4788 LPBYTE pubKey = CryptMemAlloc(keySize);
4790 if (pubKey)
4792 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pubKey,
4793 &keySize);
4794 if (ret)
4796 DWORD encodedLen = 0;
4798 ret = CryptEncodeObject(dwCertEncodingType,
4799 RSA_CSP_PUBLICKEYBLOB, pubKey, NULL, &encodedLen);
4800 if (ret)
4802 DWORD sizeNeeded = sizeof(CERT_PUBLIC_KEY_INFO) +
4803 strlen(pszPublicKeyObjId) + 1 + encodedLen;
4805 if (!pInfo)
4806 *pcbInfo = sizeNeeded;
4807 else if (*pcbInfo < sizeNeeded)
4809 SetLastError(ERROR_MORE_DATA);
4810 *pcbInfo = sizeNeeded;
4811 ret = FALSE;
4813 else
4815 *pcbInfo = sizeNeeded;
4816 pInfo->Algorithm.pszObjId = (char *)pInfo +
4817 sizeof(CERT_PUBLIC_KEY_INFO);
4818 lstrcpyA(pInfo->Algorithm.pszObjId,
4819 pszPublicKeyObjId);
4820 pInfo->Algorithm.Parameters.cbData = 0;
4821 pInfo->Algorithm.Parameters.pbData = NULL;
4822 pInfo->PublicKey.pbData =
4823 (BYTE *)pInfo->Algorithm.pszObjId
4824 + lstrlenA(pInfo->Algorithm.pszObjId) + 1;
4825 pInfo->PublicKey.cbData = encodedLen;
4826 pInfo->PublicKey.cUnusedBits = 0;
4827 ret = CryptEncodeObject(dwCertEncodingType,
4828 RSA_CSP_PUBLICKEYBLOB, pubKey,
4829 pInfo->PublicKey.pbData, &pInfo->PublicKey.cbData);
4833 CryptMemFree(pubKey);
4835 else
4836 ret = FALSE;
4838 CryptDestroyKey(key);
4840 return ret;
4843 typedef BOOL (WINAPI *ExportPublicKeyInfoExFunc)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv,
4844 DWORD dwKeySpec, DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId,
4845 DWORD dwFlags, void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo);
4847 BOOL WINAPI CryptExportPublicKeyInfoEx(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD dwKeySpec,
4848 DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags,
4849 void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo)
4851 static HCRYPTOIDFUNCSET set = NULL;
4852 BOOL ret;
4853 ExportPublicKeyInfoExFunc exportFunc = NULL;
4854 HCRYPTOIDFUNCADDR hFunc = NULL;
4856 TRACE_(crypt)("(%08lx, %d, %08x, %s, %08x, %p, %p, %d)\n", hCryptProv,
4857 dwKeySpec, dwCertEncodingType, debugstr_a(pszPublicKeyObjId), dwFlags,
4858 pvAuxInfo, pInfo, pInfo ? *pcbInfo : 0);
4860 if (!hCryptProv)
4862 SetLastError(ERROR_INVALID_PARAMETER);
4863 return FALSE;
4866 if (pszPublicKeyObjId)
4868 if (!set)
4869 set = CryptInitOIDFunctionSet(CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC,
4871 CryptGetOIDFunctionAddress(set, dwCertEncodingType, pszPublicKeyObjId,
4872 0, (void **)&exportFunc, &hFunc);
4874 if (!exportFunc)
4875 exportFunc = CRYPT_ExportRsaPublicKeyInfoEx;
4876 ret = exportFunc(hCryptProv, dwKeySpec, dwCertEncodingType,
4877 pszPublicKeyObjId, dwFlags, pvAuxInfo, pInfo, pcbInfo);
4878 if (hFunc)
4879 CryptFreeOIDFunctionAddress(hFunc, 0);
4880 return ret;
4883 BOOL WINAPI CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv,
4884 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey)
4886 return CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, pInfo,
4887 0, 0, NULL, phKey);
4890 static BOOL WINAPI CRYPT_ImportRsaPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4891 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4892 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4894 BOOL ret;
4895 DWORD pubKeySize = 0;
4897 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4898 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4900 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4901 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, NULL, &pubKeySize);
4902 if (ret)
4904 LPBYTE pubKey = CryptMemAlloc(pubKeySize);
4906 if (pubKey)
4908 ret = CryptDecodeObject(dwCertEncodingType, RSA_CSP_PUBLICKEYBLOB,
4909 pInfo->PublicKey.pbData, pInfo->PublicKey.cbData, 0, pubKey,
4910 &pubKeySize);
4911 if (ret)
4913 if(aiKeyAlg)
4914 ((BLOBHEADER*)pubKey)->aiKeyAlg = aiKeyAlg;
4915 ret = CryptImportKey(hCryptProv, pubKey, pubKeySize, 0, 0,
4916 phKey);
4918 CryptMemFree(pubKey);
4920 else
4921 ret = FALSE;
4923 return ret;
4926 typedef BOOL (WINAPI *ImportPublicKeyInfoExFunc)(HCRYPTPROV hCryptProv,
4927 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4928 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey);
4930 BOOL WINAPI CryptImportPublicKeyInfoEx(HCRYPTPROV hCryptProv,
4931 DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, ALG_ID aiKeyAlg,
4932 DWORD dwFlags, void *pvAuxInfo, HCRYPTKEY *phKey)
4934 static HCRYPTOIDFUNCSET set = NULL;
4935 BOOL ret;
4936 ImportPublicKeyInfoExFunc importFunc = NULL;
4937 HCRYPTOIDFUNCADDR hFunc = NULL;
4939 TRACE_(crypt)("(%08lx, %08x, %p, %08x, %08x, %p, %p)\n", hCryptProv,
4940 dwCertEncodingType, pInfo, aiKeyAlg, dwFlags, pvAuxInfo, phKey);
4942 if (!set)
4943 set = CryptInitOIDFunctionSet(CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC, 0);
4944 CryptGetOIDFunctionAddress(set, dwCertEncodingType,
4945 pInfo->Algorithm.pszObjId, 0, (void **)&importFunc, &hFunc);
4946 if (!importFunc)
4947 importFunc = CRYPT_ImportRsaPublicKeyInfoEx;
4948 ret = importFunc(hCryptProv, dwCertEncodingType, pInfo, aiKeyAlg, dwFlags,
4949 pvAuxInfo, phKey);
4950 if (hFunc)
4951 CryptFreeOIDFunctionAddress(hFunc, 0);
4952 return ret;